package com.yanqu.road.server.manager.activity.biaoju;

import com.google.protobuf.AbstractMessage;
import com.yanqu.road.dao.impl.activity.biaoju.*;
import com.yanqu.road.entity.activity.ActivityConditionInfo;
import com.yanqu.road.entity.activity.biaoju.*;
import com.yanqu.road.entity.activity.biaoju.config.BiaoJuCityConfig;
import com.yanqu.road.entity.activity.biaoju.config.BiaoJuDartConfig;
import com.yanqu.road.entity.activity.biaoju.config.BiaoJuTitleConfig;
import com.yanqu.road.entity.config.system.NormalWeightItem;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eUnionPosition;
import com.yanqu.road.entity.log.cross.biaoju.LogBiaoJuBuildCity;
import com.yanqu.road.entity.log.cross.biaoju.LogBiaoJuRefresh;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroupUnion;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroupUser;
import com.yanqu.road.logic.activity.biaoju.BiaoJuConfig;
import com.yanqu.road.entity.activity.biaoju.config.eBiaoJuEscortStatus;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.ActivityHelper;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.pb.UnionBasePb;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.activity.*;
import com.yanqu.road.pb.commonactivity.CommonActivityProto;
import com.yanqu.road.pb.cross.activity.CrossActivityProto;
import com.yanqu.road.pb.crossunion.activity.CrossUnionActivityRankDataProto;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.pb.rank.UnionActivityRankProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityInfoMgr;
import com.yanqu.road.server.manager.activity.ActivityMgr;
import com.yanqu.road.server.manager.log.CrossActivityLogMgr;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.union.activitygroup.Cross2UnionActivityGroupMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public class CrossBiaoJuActivity {
    private int unionGroup;
    private int activityId;
    private CrossBiaoJuData biaoJuData;
    /**
     * key: userId 个人数据
     */
    private Map<Long, CrossBiaoJuUserInfo> userInfoMap = new ConcurrentHashMap<>();
    /**
     * key: unionId 商会数据
     */
    private Map<String, CrossBiaoJuUnionInfo> unionInfoMap = new ConcurrentHashMap<>();
    /**
     * key: escort uniqueId 优质镖数据
     */
    private Map<Integer, CrossBiaoJuBestEscortData> bestEscortDataMap = new ConcurrentHashMap<>();
    /**
     * key: round 每轮优质镖数据
     */
    private Map<Integer, CrossBiaoJuBestEscortRoundInfo> bestEscortRoundInfoMap = new ConcurrentHashMap<>();

    /**
     * 优质镖唯一id
     */
    private AtomicInteger bestEscortUniqueId = new AtomicInteger(1);

    /**
     * 玩家在跑镖的唯一id
     */
    private AtomicInteger runEscortUniqueId = new AtomicInteger(1);

    /**
     * 城市当前榜单
     */
    private Map<Integer, CrossBiaoJuCityRankInfo> cityRankInfoMap = new ConcurrentHashMap<>();

    /**
     * 缓存的商会榜单
     */
    private UnionActivityRankProto.UnionActivityRankListMsg.Builder unionRankBuilder = UnionActivityRankProto.UnionActivityRankListMsg.newBuilder();
    /**
     * 缓存的个人榜单
     */
    RankProto.RankListMsg.Builder userRankBuilder = RankProto.RankListMsg.newBuilder();

    private AtomicBoolean userRankChanged = new AtomicBoolean(false);
    private AtomicBoolean unionRankChanged = new AtomicBoolean(false);

    /**
     * 每日重置检查时间
     */
    private long lastCheckTime = 0;
    /**
     * 活动结束刷新商会职位时间
     */
    private long checkActivityEndUnionPositionTime = 0;

    private Set<Long> needSyncUserSet = new HashSet<>();

    /**
     * 活动中刷到优质镖的公告
     */
    private List<BiaoJuProto.BiaoJuLockBestEscortNoticeTemp> lockBestEscortNoticeTempList = new ArrayList<>();

    public CrossBiaoJuActivity(int unionGroup, int activityId) {
        this.unionGroup = unionGroup;
        this.activityId = activityId;
        loadDb();
        if (this.biaoJuData == null) {
            this.biaoJuData = new CrossBiaoJuData(activityId, unionGroup);
        }
        checkNowRoundBestEscort();

        updateUserRankBuilder();
        updateUnionRankBuilder();
        updateCityRankInfo();
    }

    public int getUnionGroup() {
        return unionGroup;
    }

    public int getActivityId() {
        return activityId;
    }

    public void loadDb() {
        BiaoJuConfig config = getConfig();

        Map<String, CrossBiaoJuUnionData> tempBiaoJuUnionDataMap = new CrossBiaoJuUnionImpl().getCrossBiaoJuUnionData(activityId, unionGroup);
        Map<String, Map<Integer, CrossBiaoJuCityData>> tempBiaoJuCityDataMap = new CrossBiaoJuCityImpl().getCrossBiaoJuCityData(activityId, unionGroup);
        Map<Long, CrossBiaoJuUserData> tempBiaoJuUserData = new CrossBiaoJuUserImpl().getCrossBiaoJuUserData(activityId, unionGroup);
        Map<Long, List<CrossBiaoJuUserRunEscortData>> tempBiaoJuRunEscortDataMap = new CrossBiaoJuUserRunEscortImpl().getCrossBiaoJuUserRunEscortData(activityId, unionGroup);
        Map<Integer, CrossBiaoJuBestEscortData> tempBestEscortDataMap = new CrossBiaoJuBestEscortImpl().getCrossBiaoJuBestEscortData(activityId, unionGroup);

        Map<Long, CrossBiaoJuUserInfo> tempUserInfoMap = new ConcurrentHashMap<>();
        Map<String, CrossBiaoJuUnionInfo> tempUnionInfoMap = new ConcurrentHashMap<>();
        Map<Integer, CrossBiaoJuBestEscortRoundInfo> tempBestEscortRoundInfoMap = new ConcurrentHashMap<>();
        Map<Integer, CrossBiaoJuCityRankInfo> tempCityRankInfoMap = new ConcurrentHashMap<>();
        int maxBestEscortUniqueId = 0;
        int maxRunEscortUniqueId = 0;

        for (CrossBiaoJuUserData biaoJuUserData : tempBiaoJuUserData.values()) {
            CrossBiaoJuUserInfo crossBiaoJuUserInfo = new CrossBiaoJuUserInfo(biaoJuUserData);
            List<CrossBiaoJuUserRunEscortData> userRunEscortDataList = tempBiaoJuRunEscortDataMap.get(crossBiaoJuUserInfo.getUserData().getUserId());
            if (userRunEscortDataList != null) {
                userRunEscortDataList.sort((o1, o2) -> {
                    return Long.compare(o1.getFinishTime(), o2.getFinishTime());
                });

                for (CrossBiaoJuUserRunEscortData userRunEscortData : userRunEscortDataList) {
                    if (userRunEscortData.getFinishTime() == 0) {
                        crossBiaoJuUserInfo.setRunEscortData(userRunEscortData);
                    } else {
                        crossBiaoJuUserInfo.addHistoryRunEscort(userRunEscortData);
                    }

                    if (userRunEscortData.getUniqueId() > maxRunEscortUniqueId) {
                        maxRunEscortUniqueId = userRunEscortData.getUniqueId();
                    }
                }
            }

            tempUserInfoMap.put(crossBiaoJuUserInfo.getUserData().getUserId(), crossBiaoJuUserInfo);

            CrossBiaoJuUnionInfo crossBiaoJuUnionInfo = tempUnionInfoMap.get(crossBiaoJuUserInfo.getUserData().getUnionId());
            if (crossBiaoJuUnionInfo == null) {
                CrossBiaoJuUnionData unionData = tempBiaoJuUnionDataMap.get(crossBiaoJuUserInfo.getUserData().getUnionId());
                if (unionData == null) {
                    CrossBiaoJuMgr.getLogger().error("unionData is null, unionId:{}", crossBiaoJuUserInfo.getUserData().getUnionId());
                    continue;
                } else {
                    crossBiaoJuUnionInfo = new CrossBiaoJuUnionInfo(unionData);
                    tempUnionInfoMap.put(crossBiaoJuUserInfo.getUserData().getUnionId(), crossBiaoJuUnionInfo);
                }
            }

            crossBiaoJuUnionInfo.addUserInfo(crossBiaoJuUserInfo);
        }

        for (CrossBiaoJuUnionInfo biaoJuUnionInfo : tempUnionInfoMap.values()) {
            Map<Integer, CrossBiaoJuCityData> cityDataMap = tempBiaoJuCityDataMap.get(biaoJuUnionInfo.getUnionData().getUnionId());
            if (cityDataMap == null) {
                CrossBiaoJuMgr.getLogger().error("cityDataMap is null, unionId:{}", biaoJuUnionInfo.getUnionData().getUnionId());
                biaoJuUnionInfo.initCityData(config);
                cityDataMap = biaoJuUnionInfo.getCityDataMap();
            } else {
                biaoJuUnionInfo.setCityDataMap(cityDataMap);
            }

            for (CrossBiaoJuCityData cityData : cityDataMap.values()) {
                CrossBiaoJuCityRankInfo cityRankInfo = tempCityRankInfoMap.get(cityData.getCityId());
                if (cityRankInfo == null) {
                    cityRankInfo = new CrossBiaoJuCityRankInfo(cityData.getCityId());
                    tempCityRankInfoMap.put(cityData.getCityId(), cityRankInfo);
                }

                cityRankInfo.addCityData(cityData);
            }
        }

        for (CrossBiaoJuBestEscortData bestEscortData : tempBestEscortDataMap.values()) {
            CrossBiaoJuBestEscortRoundInfo bestEscortRoundInfo = tempBestEscortRoundInfoMap.get(bestEscortData.getRound());
            if (bestEscortRoundInfo == null) {
                bestEscortRoundInfo = new CrossBiaoJuBestEscortRoundInfo(bestEscortData.getRound());
                tempBestEscortRoundInfoMap.put(bestEscortData.getRound(), bestEscortRoundInfo);
            }

            bestEscortRoundInfo.addDbBestEscortData(bestEscortData);

            if (bestEscortData.getUniqueId() > maxBestEscortUniqueId) {
                maxBestEscortUniqueId = bestEscortData.getUniqueId();
            }
        }

        this.biaoJuData = new CrossBiaoJuImpl().getCrossBiaoJuData(activityId, unionGroup);

        this.userInfoMap = tempUserInfoMap;
        this.unionInfoMap = tempUnionInfoMap;
        this.bestEscortDataMap = tempBestEscortDataMap;
        this.bestEscortRoundInfoMap = tempBestEscortRoundInfoMap;
        this.cityRankInfoMap = tempCityRankInfoMap;
        this.bestEscortUniqueId = new AtomicInteger(maxBestEscortUniqueId + 1);
        this.runEscortUniqueId = new AtomicInteger(maxRunEscortUniqueId + 1);


        List<CrossBiaoJuUserRunEscortData> needNoticeList = new ArrayList<>();
        for (CrossBiaoJuUserInfo biaoJuUserInfo : this.userInfoMap.values()) {
            CrossBiaoJuUserRunEscortData runEscortData = biaoJuUserInfo.getRunEscortData();
            if (runEscortData == null) {
                continue;
            }
            if (runEscortData.getBestEscortId() == 0) {
                continue;
            }

            needNoticeList.add(runEscortData);
        }

        needNoticeList.sort((o1, o2) -> {
            return Long.compare(o1.getTakeTime(), o2.getTakeTime());
        });

        for (CrossBiaoJuUserRunEscortData runEscortData : needNoticeList) {
            addLockBestEscortNotice(runEscortData);
        }
    }

    public void save() {
        List<CrossBiaoJuUnionInfo> unionInfoList = getUnionInfoList();

        for (CrossBiaoJuUnionInfo biaoJuUnionInfo : unionInfoList) {
            biaoJuUnionInfo.save();
        }

        List<CrossBiaoJuBestEscortData> bestEscortDataList = new ArrayList<>();
        synchronized (bestEscortDataMap) {
            bestEscortDataList.addAll(bestEscortDataMap.values());
        }

        for (CrossBiaoJuBestEscortData bestEscortData : bestEscortDataList) {
            if (bestEscortData.isInsertOption()) {
                new CrossBiaoJuBestEscortImpl().add(bestEscortData);
            } else if (bestEscortData.isUpdateOption()) {
                new CrossBiaoJuBestEscortImpl().update(bestEscortData);
            }
        }

        if (biaoJuData.isInsertOption()) {
            new CrossBiaoJuImpl().add(biaoJuData);
        } else if (biaoJuData.isUpdateOption()) {
            new CrossBiaoJuImpl().update(biaoJuData);
        }
    }

    public BiaoJuConfig getConfig() {
        return CrossBiaoJuConfigMgr.getBiaoJuConfig(activityId);
    }

    /**
     * 创建当前轮的优质镖数据,一般进来都是第一次创建, 用保底数据
     */
    private void checkNowRoundBestEscort() {
        BiaoJuConfig config = getConfig();
        if (config == null) {
            return;
        }

        int nowRound = config.getNowRound();
        if (nowRound == 0) {
            return;
        }
        CrossBiaoJuBestEscortRoundInfo escortRoundInfo = null;
        synchronized (bestEscortRoundInfoMap) {
            escortRoundInfo = bestEscortRoundInfoMap.get(nowRound);
            if (escortRoundInfo != null) { //不要重复生成
                return;
            }

            if (escortRoundInfo == null) {
                escortRoundInfo = new CrossBiaoJuBestEscortRoundInfo(nowRound);
                bestEscortRoundInfoMap.put(nowRound, escortRoundInfo);
            }
        }

        createBestEscort(escortRoundInfo);
    }

    /**
     * 回合变化任务
     */
    public void roundChangeTask() {
//        createNowRoundBestEscort();
        biaoJuData.setNowRound(getConfig().getNowRound());
        roundSettleTask();
        checkNextRoundBestEscort();
        dayReset();

        syncUserData();
    }

    /**
     * 结算城市排名, 同时生成下一轮的优质镖数据
     */
    private void roundSettleTask() {
        BiaoJuConfig config = getConfig();
        if (config == null) {
            return;
        }
        long lastSettleRound = biaoJuData.getSettleRound();
        if (lastSettleRound >= config.getNowRound()) {
            return;
        }

        int beforeRound = config.getBeforeRound();
        if (beforeRound > 0 && lastSettleRound < beforeRound) {
            //上一轮没结算,结算一下
            roundSettle(beforeRound);
            return;
        }

        long nowCityRankSettleTime = config.getNowCityRankSettleTime();
        long currentTime = DateHelper.getCurrentTime();
        if (currentTime <= nowCityRankSettleTime + DateHelper.SECOND_MILLIONS) { //多等一秒
            return;
        }
        int nowRound = config.getNowRound();

        roundSettle(nowRound);
    }

    private void roundSettle(int round) {
        biaoJuData.setSettleRound(round);
        //更新一下最新的排名
        updateCityRankInfo();
        //cityRankInfoMap的key是跟着配置走,固定的,不用锁
        for (CrossBiaoJuCityRankInfo cityRankInfo : cityRankInfoMap.values()) {
            for (CrossBiaoJuCityData cityData : cityRankInfo.getCityDataList()) {
                cityData.updateHistoryRank(round, cityData.getRank(), cityData.getRankScore(), cityData.getRoundScore());
                cityData.setLastRank(cityData.getRank());
                cityData.setRoundScore(0);
                cityData.setLastRankScore(cityData.getRankScore());
            }
        }
    }

    /**
     * 检查并生成下一轮的优质镖数据,只在城市榜结算的前N分钟内生成
     */
    public void checkNextRoundBestEscort() {
        BiaoJuConfig config = getConfig();
        if (config == null) {
            return;
        }
        //生成下一轮的优质镖数据
        if (config.isLastRound()) {
            return;
        }

        long nowCityRankSettleTime = config.getNowCityRankSettleTime();
        long currentTime = DateHelper.getCurrentTime();
        if (currentTime <= nowCityRankSettleTime + DateHelper.SECOND_MILLIONS) { //多等一秒
            return;
        }

        int nextRound = config.getNextRound();
        CrossBiaoJuBestEscortRoundInfo escortRoundInfo = null;
        synchronized (bestEscortRoundInfoMap) {
            escortRoundInfo = bestEscortRoundInfoMap.get(nextRound);
            if (escortRoundInfo != null) { //不要重复生成
                return;
            }

            if (escortRoundInfo == null) {
                escortRoundInfo = new CrossBiaoJuBestEscortRoundInfo(nextRound);
                bestEscortRoundInfoMap.put(nextRound, escortRoundInfo);
            }
        }

        createBestEscort(escortRoundInfo);
    }

    /**
     * 刷新优质镖的品质
     */
    private void refreshNowRoundBestQualityList() {
        BiaoJuConfig config = getConfig();
        int nowRound = config.getNowRound();
        //统计所有的镖师等级对应人数
        Map<Integer, Integer> titleNumMap = new HashMap<>();
        Map<Integer, BigDecimal> qualityCalcMap = new HashMap<>();

        List<CrossBiaoJuUserInfo> userInfoList = getUserInfoList();
        for (CrossBiaoJuUserInfo biaoJuUserInfo : userInfoList) {
            int level = biaoJuUserInfo.getUserData().getLevel();
            Integer num = titleNumMap.getOrDefault(level, 0);
            num++;
            titleNumMap.put(level, num);
        }

        //每个品质的高级镖单的数量=累计(等级镖师人数*镖师系数)*镖单系数，有保底
        //优质镖的定义改了,取统计的有数量的最高3个品质

        List<Integer> qualityList = new ArrayList<>();
        //先默认前3个品质
        for (int quality = config.getHighQualityDefine(); quality < config.getHighQualityDefine() + 3; quality++) {
            qualityList.add(quality);
        }

        for (int quality = config.getHighQualityDefine(); quality <= config.getMaxQuality(); quality++) {
            BigDecimal titleAmount = BigDecimal.ZERO;
            for (BiaoJuTitleConfig titleConfig : config.getTitleConfigMap().values()) {
                BigDecimal titleHighParam = BigDecimal.valueOf(titleConfig.getHighDartParamProperty().getCountByGoodsId(quality).intValue());
                BigDecimal takeNum = BigDecimal.valueOf(titleNumMap.getOrDefault(titleConfig.getId(), 0));
                titleAmount = titleAmount.add(takeNum.multiply(titleHighParam).divide(BigDecimal.valueOf(1000), 8, BigDecimal.ROUND_DOWN));
            }
            int highQualityEscortParam1 = config.getHighQualityEscortParam1(quality);
            BigDecimal result = titleAmount.multiply(BigDecimal.valueOf(highQualityEscortParam1)).divide(BigDecimal.valueOf(1000));
            qualityCalcMap.put(quality, result);

            if (result.compareTo(BigDecimal.ZERO) > 0 && quality >= config.getHighQualityDefine() + 3) {//结果大于0的,放进去
                qualityList.add(quality);
            }
        }

        //数值说定死,只保留3个品质
        while (qualityList.size() > 3) {
            qualityList.remove(0);
        }

        biaoJuData.setBestQualityList(qualityList);
        biaoJuData.updateHistoryLevelAmount(nowRound, titleNumMap, qualityCalcMap);
    }

    private void createBestEscort(CrossBiaoJuBestEscortRoundInfo escortRoundInfo) {
        refreshNowRoundBestQualityList();

        BiaoJuConfig config = getConfig();
        for (Integer quality : biaoJuData.getBestQualityList()) {
            BigDecimal result = biaoJuData.getRoundCalcResult(biaoJuData.getSettleRound(), quality);
            int createNum = result.setScale(0, BigDecimal.ROUND_UP).intValue();
            int minNum = config.getHighQualityEscortMinNum(quality);
            if (createNum < minNum) {
                createNum = minNum;
            }

            synchronized (bestEscortDataMap) {
                int uniqueId = bestEscortUniqueId.getAndIncrement();
                CrossBiaoJuBestEscortData bestEscortData = new CrossBiaoJuBestEscortData(activityId, uniqueId, unionGroup, escortRoundInfo.getRound(), quality, createNum);
                bestEscortDataMap.put(bestEscortData.getUniqueId(), bestEscortData);

                escortRoundInfo.addNewBestEscortData(bestEscortData);
            }
        }
    }

    /**
     * 跑镖定时任务
     */
    public void runEscortTask() {
        if (!ActivityMgr.activityInTime(getConfig().getActivityInfo())) {
            return;
        }
        List<CrossBiaoJuUserInfo> userInfoList = getUserInfoList();

        for (CrossBiaoJuUserInfo userInfo : userInfoList) {
            if (userInfo.getRunEscortData() == null) {
                continue;
            }

            autoStartRunEscortCheck(userInfo);

            checkUserRunEscortEnd(userInfo);
        }
    }

    /**
     * 检查玩家资格,如果有资格生成数据
     *
     * @param userId
     */
    public CrossBiaoJuUserInfo getUserInfoNewIfNull(long userId) {
        if (userInfoMap.containsKey(userId)) {
            return userInfoMap.get(userId);
        }

        if (userId == 0) {
            return null;
        }

        UnionActivityGroupUnion unionGroupData = Cross2UnionActivityGroupMgr.getUnionData(activityId, userId);
        if (unionGroupData == null) {
            return null;
        }

        if (unionGroupData.getGroupId() != unionGroup) {
            CrossBiaoJuMgr.getLogger().error("活动分组和玩家分组不一致! activityId:{} userId:{} unionGroup:{} groupId:{}", activityId, userId, unionGroup, unionGroupData.getGroupId());
            return null;
        }

        boolean isNewUnion = false;
        CrossBiaoJuUnionInfo biaoJuUnionInfo = unionInfoMap.get(unionGroupData.getUnionUid());
        if (biaoJuUnionInfo == null) {
            synchronized (unionInfoMap) {
                biaoJuUnionInfo = unionInfoMap.get(unionGroupData.getUnionUid());
                if (biaoJuUnionInfo == null) {
                    CrossBiaoJuUnionData unionData = new CrossBiaoJuUnionData(activityId, unionGroupData.getUnionUid(), unionGroup);
                    biaoJuUnionInfo = new CrossBiaoJuUnionInfo(unionData);
                    biaoJuUnionInfo.initCityData(getConfig());
                    unionInfoMap.put(unionGroupData.getUnionUid(), biaoJuUnionInfo);

                    isNewUnion = true;
                    for (CrossBiaoJuCityData cityData : biaoJuUnionInfo.getCityDataList()) {
                        CrossBiaoJuCityRankInfo cityRankInfo = cityRankInfoMap.get(cityData.getCityId());
                        if (cityRankInfo == null) {
                            cityRankInfo = new CrossBiaoJuCityRankInfo(cityData.getCityId());
                            cityRankInfoMap.put(cityData.getCityId(), cityRankInfo);
                        }
                        cityRankInfo.addCityData(cityData);
                    }

                }
            }
        }

        CrossBiaoJuUserInfo biaoJuUserInfo = userInfoMap.get(userId);
        if (biaoJuUserInfo == null) {
            synchronized (userInfoMap) {
                biaoJuUserInfo = userInfoMap.get(userId);
                if (biaoJuUserInfo == null) {
                    CrossBiaoJuUserData userData = new CrossBiaoJuUserData(activityId, userId, unionGroup, unionGroupData.getUnionUid());
                    biaoJuUserInfo = new CrossBiaoJuUserInfo(userData);
                    biaoJuUserInfo.setCanBePullQuality(new ArrayList<>(getConfig().getAllDartGear()), new ArrayList<>(), 0);
                    userInfoMap.put(userId, biaoJuUserInfo);
                    biaoJuUnionInfo.addUserInfo(biaoJuUserInfo);
                }
            }
        }


        if (isNewUnion) {
            updateCityRankInfo();
        }

        return biaoJuUserInfo;
    }

    public CrossBiaoJuUserInfo getUserInfoOnlyGet(long userId) {
        return userInfoMap.get(userId);
    }

    public BiaoJuProto.BiaoJuMainSceneRespMsg.Builder getMainSceneMsg(long userId) {
        BiaoJuProto.BiaoJuMainSceneRespMsg.Builder respMsg = BiaoJuProto.BiaoJuMainSceneRespMsg.newBuilder();
        respMsg.setRet(0);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoNewIfNull(userId);
        if (userInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        checkUserRunEscortEnd(userInfo);

        BiaoJuProto.BiaoJuMainSceneTemp.Builder mainSceneTemp = parseMainSceneTemp(userInfo);
        if (mainSceneTemp == null) {
            return respMsg.setRet(GameErrorCode.E_ERROR_DATA);
        }

        respMsg.setScene(mainSceneTemp);

        return respMsg;
    }

    public CrossBiaoJuUnionInfo getUnionInfo(String unionId) {
        return unionInfoMap.get(unionId);
    }

    public BiaoJuProto.BiaoJuMainSceneTemp.Builder parseMainSceneTemp(CrossBiaoJuUserInfo userInfo) {
        BiaoJuConfig config = getConfig();
        if (config == null) {
            return null;
        }
        BiaoJuProto.BiaoJuMainSceneTemp.Builder temp = BiaoJuProto.BiaoJuMainSceneTemp.newBuilder();
        temp.setRound(config.getNowRound());
        temp.setUserData(parseUserTemp(userInfo));
        int myRank = userInfo.getUserData().getRank();
        RankProto.RankListMsg rankBuild = getUserRankBuild();
        if (myRank > rankBuild.getRankListCount()) {
            myRank = -1;
        }
        temp.setUserRank(myRank);

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());

        temp.setUnionData(parseUnionTemp(unionInfo));
        int myUnionRank = unionInfo.getUnionData().getRank();
        UnionActivityRankProto.UnionActivityRankListMsg unionRankBuild = getUnionRankBuild();
        if (myUnionRank > unionRankBuild.getRankListCount()) {
            myUnionRank = -1;
        }
        temp.setUnionRank(myUnionRank);
        temp.setRefreshTime(config.getThisRoundEndTime());
        temp.setRemainBestEscortCount(getRemainBestEscortCount());

        for (CrossBiaoJuUserInfo biaoJuUserInfo : unionInfo.getMemberInfoList()) {
            BiaoJuProto.BiaoJuMemberEscortSimpleTemp.Builder escortSimple = parseMemberEscortSimple(biaoJuUserInfo, userInfo.getUserData().getUserId());
            if (escortSimple == null) {
                continue;
            }
            temp.addMemberEscortList(escortSimple);
        }

        temp.addAllCanBePullQuality(userInfo.getUserData().getCanBePullQuality());
        temp.setQualitySwitch(userInfo.getUserData().getSettingSwitch());
        temp.addAllBestQuality(biaoJuData.getBestQualityList());

        CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
        if (runEscortData != null) {
            temp.setEscortInfo(parseEscortDetail(runEscortData, userInfo.getUserData().getUserId()));
        }

        return temp;
    }

    public BiaoJuProto.BiaoJuUserTemp.Builder parseUserTemp(CrossBiaoJuUserInfo userInfo) {
        BiaoJuProto.BiaoJuUserTemp.Builder temp = BiaoJuProto.BiaoJuUserTemp.newBuilder();
        temp.setUserId(userInfo.getUserData().getUserId());
        temp.setLevel(userInfo.getUserData().getLevel());
        temp.setExp(userInfo.getUserData().getExp());
        temp.setMoney(userInfo.getUserData().getMoney());
        temp.setDayJoinNum(userInfo.getUserData().getDayJoinNum());
        temp.setUnionExpAdd(userInfo.getUserData().getUnionExpAdd());
        temp.setLastBuildTime(userInfo.getUserData().getLastBuildTime());
        temp.setDayJoinRewardNum(userInfo.getUserData().getDayJoinRewardNum());
        temp.setDayUnionExpAdd(userInfo.getUserData().getDayUnionExpAdd());
        temp.setRoundBuildNum(getUserRoundBuildNum(userInfo.getUserData().getUserId(), getConfig().getNowRound()));
        temp.addAllQuality(userInfo.getUserData().getCanBePullQuality());
        temp.setQualitySwitch(userInfo.getUserData().getSettingSwitch());
        temp.addAllCanBePullId(userInfo.getUserData().getCanPullId());

        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userInfo.getUserData().getUserId());
        temp.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));

        return temp;
    }

    /**
     * 没进过活动的玩家数据
     * @return
     */
    public BiaoJuProto.BiaoJuUserTemp.Builder parseEmptyUserTemp(long userId) {
        BiaoJuProto.BiaoJuUserTemp.Builder temp = BiaoJuProto.BiaoJuUserTemp.newBuilder();
        temp.setUserId(userId);
        temp.setLevel(1);
        temp.setExp(0);
        temp.setMoney(0);
        temp.setDayJoinNum(0);
        temp.setUnionExpAdd(0);
        temp.setLastBuildTime(0);
        temp.setDayJoinRewardNum(0);
        temp.setDayUnionExpAdd(0);
        temp.setRoundBuildNum(0);

        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        temp.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));

        return temp;
    }


    public BiaoJuProto.BiaoJuUnionTemp.Builder parseUnionTemp(CrossBiaoJuUnionInfo biaojuUnionInfo) {
        BiaoJuProto.BiaoJuUnionTemp.Builder temp = BiaoJuProto.BiaoJuUnionTemp.newBuilder();
        temp.setUnionId(biaojuUnionInfo.getUnionData().getUnionId());
        temp.setUnionLevel(biaojuUnionInfo.getUnionData().getLevel());
        temp.setUnionExp(biaojuUnionInfo.getUnionData().getExp());
        UnionActivityGroupUnion unionData = Cross2UnionActivityGroupMgr.getUnionData(activityId, biaojuUnionInfo.getUnionData().getUnionId(), unionGroup);
        temp.setUnionBaseData(UnionBasePb.parseUnionBaseTempMsg(unionData.getUnionBaseInfo()));

        return temp;
    }

    public int getRemainBestEscortCount() {
        BiaoJuConfig config = getConfig();
        int nowRound = config.getNowRound();
        CrossBiaoJuBestEscortRoundInfo roundInfo = bestEscortRoundInfoMap.get(nowRound);
        if (roundInfo == null) {
            return 0;
        }
        return roundInfo.getRemainBestEscortCount();
    }

    public BiaoJuProto.BiaoJuMemberEscortSimpleTemp.Builder parseMemberEscortSimple(CrossBiaoJuUserInfo userInfo, long reqUserId) {
        CrossBiaoJuUserRunEscortData escortData = userInfo.getRunEscortData();
        if (escortData == null) {
            escortData = userInfo.getLastOneHistoryEscort();
        }

        if (escortData == null) {
            return null;
        }

        return parseMemberEscortSimple(escortData, reqUserId);
    }

    public BiaoJuProto.BiaoJuMemberEscortSimpleTemp.Builder parseMemberEscortSimple(CrossBiaoJuUserRunEscortData escortData, long reqUserId) {
        BiaoJuProto.BiaoJuMemberEscortSimpleTemp.Builder temp = BiaoJuProto.BiaoJuMemberEscortSimpleTemp.newBuilder();
        temp.setUserId(escortData.getUserId());
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(escortData.getUserId());
        temp.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));

        temp.setEscortId(escortData.getEscortId());
        temp.setCityId(escortData.getCityId());
        temp.setStatus(escortData.getStatus());
        temp.setNextStatusTime(0);
        temp.setLoseNum(escortData.getLoseNum());

        if (temp.getStatus() == eBiaoJuEscortStatus.Taken.getValue()) { //被接镖有走镖倒计时
            temp.setNextStatusTime(escortData.getTakeTime() + getConfig().getPrepareTimeSecondMillions());
        } else if (temp.getStatus() == eBiaoJuEscortStatus.Running.getValue()) { //押镖中有完成倒计时,要减去加速的时间
            temp.setNextStatusTime(escortData.getRunStartTime() + getConfig().getEscortMinSecondMillions() - escortData.getSpeedUpTime());
        }
        if (escortData.getRunStartTime() > 0) {
            temp.setCityBuffAddition(escortData.getCityAddition());
            temp.setTitleLevel(escortData.getUserLevel());
            temp.setUnionLevel(escortData.getUnionLevel());
        } else {
            temp.setCityBuffAddition(getCityRankAddition(escortData.getUserId()));
            temp.setTitleLevel(getUserLevel(escortData.getUserId()));
            temp.setUnionLevel(getUnionLevel(escortData.getUserId()));
        }

        temp.setRemainBlood(escortData.getRemainBlood());
//        temp.setBattleValue(escortData.getBattleValue());
        temp.setBattleValue(refreshRunEscortBattleValue(escortData));
        temp.setRelationType(escortData.isInTeam(reqUserId) ? 1 : 0);
        temp.setEscortUniqueId(escortData.getUniqueId());

        return temp;
    }
//
//    public BiaoJuProto.BiaoJuMemberEscortSimpleTemp.Builder parseMemberEscortSimple(CrossBiaoJuBestEscortData bestEscortData, long reqUserId) {
//        BiaoJuProto.BiaoJuMemberEscortSimpleTemp.Builder temp = BiaoJuProto.BiaoJuMemberEscortSimpleTemp.newBuilder();
//        temp.setEscortId(bestEscortData.getEscortId());
//        temp.setCityId(bestEscortData.getCityId());
//        temp.setUserId(bestEscortData.getTakeUserId());
//        temp.setCityBuffAddition(getCityRankAddition(reqUserId));
//        temp.setRelationType(0);
//        temp.setStatus(eBiaoJuEscortStatus.Init.getValue());
//        if (bestEscortData.getRound() != getConfig().getNowRound()) {
//            temp.setStatus(eBiaoJuEscortStatus.Expired.getValue()); //已过期
//        }
//        temp.setNextStatusTime(0);
//
//        if (bestEscortData.getTakeUserId() > 0) {//被接镖的优质镖,不是本回合的就是过期的,是本回合的不是被接玩家身上的就是已完成的。
//            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(bestEscortData.getTakeUserId());
//            temp.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
//
//            if (bestEscortData.getRound() == getConfig().getNowRound()) {
//                temp.setStatus(eBiaoJuEscortStatus.Locked.getValue()); //锁定中,被玩家刷到的
//                CrossBiaoJuUserInfo takeUserInfo = getUserInfoOnlyGet(bestEscortData.getTakeUserId());
//                if (takeUserInfo != null) {
//                    CrossBiaoJuUserRunEscortData runEscortData = takeUserInfo.findBestEscortData(bestEscortData.getUniqueId());
//                    if (runEscortData != null) {//被接了的
//                        temp = parseMemberEscortSimple(runEscortData, reqUserId);
//                    }
//                }
//            }
//        }
//
//        return temp;
//    }

    public BiaoJuProto.BiaoJuLockBestEscortNoticeTemp.Builder parseLockBestEscortNotice(CrossBiaoJuUserRunEscortData runEscortData) {
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(runEscortData.getUserId());
        if (userBaseInfo == null) {
            return null;
        }

        BiaoJuProto.BiaoJuLockBestEscortNoticeTemp.Builder temp = BiaoJuProto.BiaoJuLockBestEscortNoticeTemp.newBuilder();
        temp.setUserId(runEscortData.getUserId());
        temp.setUserName(userBaseInfo.getNickName());
        temp.setServerId(userBaseInfo.getServerId());
        temp.setEscortId(runEscortData.getEscortId());
        temp.setCityId(runEscortData.getCityId());
        temp.setLockTime(runEscortData.getTakeTime());
        temp.setDecoration(userBaseInfo.getDecoration());

        return temp;
    }

    public int getCityRankAddition(long userId, int cityId) {
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return 0;
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return 0;
        }

        CrossBiaoJuCityData biaoJuCityData = unionInfo.getCityDataMap().get(cityId);
        if (biaoJuCityData == null) {
            return 0;
        }

        int rank = biaoJuCityData.getLastRank();
        return getConfig().getCityRankAddition(rank);
    }

    public int getUserLevel(long userId) {
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return 0;
        }
        return userInfo.getUserData().getLevel();
    }

    public int getUnionLevel(long userId) {
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return 0;
        }
        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return 0;
        }
        return unionInfo.getUnionData().getLevel();
    }

    public int getCityRankAddition(long userId) {
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return 0;
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return 0;
        }

        int addition = 0;
        for (CrossBiaoJuCityData biaoJuCityData : unionInfo.getCityDataList()) {
            int rank = biaoJuCityData.getLastRank();
            addition += getConfig().getCityRankAddition(rank);
        }

        return addition;
    }

    public int getUnionLevelAddition(long userId) {
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return 0;
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return 0;
        }

        return getConfig().getUnionLevelAddition(unionInfo.getUnionData().getLevel());
    }

    /**
     * 获取招募中的镖列表,走镖中的也要
     *
     * @param userId
     * @return
     */
    public BiaoJuProto.BiaoJuGetRecruitListRespMsg.Builder getInRecruitEscortList(long userId) {
        BiaoJuProto.BiaoJuGetRecruitListRespMsg.Builder resp = BiaoJuProto.BiaoJuGetRecruitListRespMsg.newBuilder();
        resp.setRet(0);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        for (CrossBiaoJuUserInfo biaoJuUserInfo : unionInfo.getMemberInfoList()) {
//            if (biaoJuUserInfo.getUserData().getUserId() == userId) {
//                continue;
//            }

            CrossBiaoJuUserRunEscortData runEscortData = biaoJuUserInfo.getRunEscortData();
            if (runEscortData == null) {
                continue;
            }

//            if (runEscortData.getBattleLogList().size() > 0) {//押镖中不能招募
//                continue;
//            }

            resp.addEscortList(parseEscortDetail(runEscortData, userId));
        }

        return resp;
    }

    public BiaoJuProto.BiaoJuGetMyEscortInfoRespMsg.Builder getMyEscortInfo(long userId) {
        BiaoJuProto.BiaoJuGetMyEscortInfoRespMsg.Builder resp = BiaoJuProto.BiaoJuGetMyEscortInfoRespMsg.newBuilder();
        resp.setRet(0);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        synchronized (userInfo) {
            checkUserRunEscortEnd(userInfo);
            CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
            if (runEscortData != null) {
                resp.setEscortInfo(parseEscortDetail(runEscortData, userId));
            } else {
                checkUserWaitTakeList(userInfo);
                List<BiaoJuUserEscortInfo> waitTakeList = userInfo.getWaitTakeList();
                for (int i = 0; i < waitTakeList.size(); i++) {
                    BiaoJuUserEscortInfo userEscortInfo = waitTakeList.get(i);
                    BiaoJuProto.BiaoJuWaitTakeEscortTemp.Builder builder = BiaoJuProto.BiaoJuWaitTakeEscortTemp.newBuilder();
                    builder.setEscortId(userEscortInfo.getEscortId());
                    builder.setCityId(userEscortInfo.getCityId());
                    builder.setId(i + 1);
                    builder.setCityAddition(getCityRankAddition(userId));
                    resp.addWaitTakeList(builder);
                }
            }
        }
        BiaoJuTitleConfig biaoJuTitleConfig = config.getTitleConfigMap().get(userInfo.getUserData().getLevel());
        if (biaoJuTitleConfig != null) {
            resp.setIsNeedTips(true);
            int maxBestQuality = getMaxBestQuality();
            for (NormalWeightItem normalWeightItem : biaoJuTitleConfig.getWeightList()) {
                if (normalWeightItem.getValue().intValue() < maxBestQuality) {
                    resp.setIsNeedTips(false);
                    break;
                }
            }
        }

        CrossBiaoJuUserRunEscortData lastOneEscort = userInfo.getLastOneEscort();
        if (lastOneEscort != null) {
            for (BiaoJuTeamUserInfo teamUserInfo : lastOneEscort.getTeamUserList()) {
                CrossBiaoJuUserInfo targetUserInfo = getUserInfoOnlyGet(teamUserInfo.getUserId());
                if (targetUserInfo == null) {
                    continue;
                }
                resp.addTogetherHistory(parseUserTemp(targetUserInfo));
            }
        }

        resp.setRemainBestEscortCount(getRemainBestEscortCount());
        resp.setNextRefreshTime(getConfig().getThisRoundEndTime());

        return resp;
    }

    public BiaoJuProto.BiaoJuMemberEscortDetailTemp.Builder parseEscortDetail(CrossBiaoJuUserRunEscortData escortData, long reqUserId) {
        BiaoJuProto.BiaoJuMemberEscortDetailTemp.Builder temp = BiaoJuProto.BiaoJuMemberEscortDetailTemp.newBuilder();
        temp.setSimpleInfo(parseMemberEscortSimple(escortData, reqUserId));

        CrossBiaoJuUserInfo openUserInfo = getUserInfoOnlyGet(escortData.getUserId());
        if (openUserInfo != null) {
            BiaoJuProto.BiaoJuUserTemp.Builder memberBuilder = parseUserTemp(openUserInfo);
            if (escortData.getBattleLogList().size() > 0) {//有战斗日志后等级固定
                memberBuilder.setLevel(escortData.getUserLevel());
            }
            temp.addMemberList(memberBuilder);
        }

        for (BiaoJuTeamUserInfo teamUser : escortData.getTeamUserList()) {
            CrossBiaoJuUserInfo teamUserInfo = getUserInfoOnlyGet(teamUser.getUserId());
            if (teamUserInfo == null) {
                continue;
            }
            BiaoJuProto.BiaoJuUserTemp.Builder memberBuilder = parseUserTemp(teamUserInfo);
            if (escortData.getBattleLogList().size() > 0) {//有战斗日志后,等级固定
                memberBuilder.setLevel(teamUser.getLevel());
            }
            temp.addMemberList(memberBuilder);
        }

        for (int i = 0; i < escortData.getBattleLogList().size(); i++) {
            BiaoJuEscortBattleLog battleLog = escortData.getBattleLogList().get(i);
            int coordId = i + 1;
            BiaoJuProto.BiaoJuEscortBattleLogTemp.Builder logBuilder = BiaoJuProto.BiaoJuEscortBattleLogTemp.newBuilder();
            logBuilder.setPlaceCoordId(coordId);
            logBuilder.setBattleValue(battleLog.getBattleValue());
            logBuilder.setDecBlood(battleLog.getDecBlood());
            logBuilder.setEventId(battleLog.getEventId());
            logBuilder.setBattleTime(battleLog.getBattleTime());
            logBuilder.setResult(battleLog.getResult());

            temp.addBattleLogList(logBuilder);
        }

        return temp;
    }

    /**
     * 检查玩家身上的镖单,没有时,抽取新的镖单,这里不需要返还优质镖,因为跨轮次了
     *
     * @param userInfo
     */
    public void checkUserWaitTakeList(CrossBiaoJuUserInfo userInfo) {
        BiaoJuConfig config = getConfig();
        if (!userInfo.getUserData().getWaitTakeList().isEmpty() && config.isTimeInNowRound(userInfo.getUserData().getLastRefreshTime())) {
            return;
        }
        if (userInfo.getRunEscortData() != null) {
            return;
        }

        //先抽品质
        //再根据品质抽镖单,优质镖要从公共池里抽,没有优质镖了再补充普通镖
        refreshUserWaitTakeList(userInfo);
    }

    /**
     * 这个方法会把优质镖抽取出来,不能乱用
     *
     * @param userInfo
     * @return
     */
    public List<BiaoJuUserEscortInfo> randomUserWaitTakeEscortList(CrossBiaoJuUserInfo userInfo) {
        BiaoJuConfig config = getConfig();

        //先抽品质
        //再根据品质抽镖单,优质镖要从公共池里抽,没有优质镖了再补充普通镖
        List<Integer> qualityList = config.randomDartQualityList(userInfo.getUserData().getLevel(), biaoJuData.getBestQualityList());

        int minBestQuality = getMinBestQuality();

        List<BiaoJuUserEscortInfo> randomList = new ArrayList<>();

        for (Integer takeQuality : qualityList) {
            boolean isTakeBest = false;
            if (!biaoJuData.isBestQuality(takeQuality)) {
                int escortDartId = config.randomOnceEscortDartId(takeQuality);
                int cityId = config.randomOnceCityId();

                BiaoJuUserEscortInfo biaoJuUserEscortInfo = new BiaoJuUserEscortInfo();
                biaoJuUserEscortInfo.setBestEscortId(0);
                biaoJuUserEscortInfo.setEscortId(escortDartId);
                biaoJuUserEscortInfo.setCityId(cityId);

                randomList.add(biaoJuUserEscortInfo);
            } else {
                CrossBiaoJuBestEscortRoundInfo escortRoundInfo = bestEscortRoundInfoMap.get(config.getNowRound());
                if (escortRoundInfo != null) {
                    for (Integer bestQuality = takeQuality; bestQuality >= minBestQuality; bestQuality--) {//当前品质的优质镖取不到,要往下取
                        CrossBiaoJuBestEscortData bestEscortData = escortRoundInfo.randomPopOnceBestEscort(bestQuality, userInfo.getUserData().getUserId());
                        if (bestEscortData != null) {
                            isTakeBest = true;

                            BiaoJuUserEscortInfo biaoJuUserEscortInfo = new BiaoJuUserEscortInfo();
                            biaoJuUserEscortInfo.setBestEscortId(bestEscortData.getUniqueId());
                            biaoJuUserEscortInfo.setEscortId(config.randomOnceEscortDartId(bestEscortData.getQuality()));
                            biaoJuUserEscortInfo.setCityId(config.randomOnceCityId());

                            randomList.add(biaoJuUserEscortInfo);
                            break;
                        }
                    }
                }

                if (!isTakeBest) {//没有优质镖可以抽,补一个非优质镖
                    Integer tempQuality = config.randomDartQualityListExcludeBest(userInfo.getUserData().getLevel(), minBestQuality);
                    if (tempQuality != 0) {
                        int escortDartId = config.randomOnceEscortDartId(tempQuality);
                        BiaoJuUserEscortInfo biaoJuUserEscortInfo = new BiaoJuUserEscortInfo();
                        biaoJuUserEscortInfo.setBestEscortId(0);
                        biaoJuUserEscortInfo.setEscortId(escortDartId);
                        biaoJuUserEscortInfo.setCityId(config.randomOnceCityId());

                        randomList.add(biaoJuUserEscortInfo);
                    }
                }
            }
        }

        //策划需求又改啦，不要保底了
        //没刷到高品质,检查是否触发保底
//        //镖师有概率刷到高品质的才检查
//        Set<Integer> canRandomHighQualityList = new HashSet<>();
//        for (NormalWeightItem normalWeightItem : biaoJuTitleConfig.getWeightList()) {
//            int canRandomQuality = normalWeightItem.getValue().intValue();
//            if (biaoJuData.isBestQuality(canRandomQuality)) {
//                canRandomHighQualityList.add(canRandomQuality);
//            }
//        }
//        if (!canRandomHighQualityList.isEmpty()) {
//            if (isTakeBest) {
//                userInfo.resetGuaranteeRefreshCount();
//            }else {
//                userInfo.addGuaranteeRefreshCount(1);
//                if (userInfo.getUserData().getGuaranteeAmount() >= config.getRefreshHighQualityCount()) {
//                    //触发保底去抽优质镖,抽到才重置保底
//                    CrossBiaoJuBestEscortRoundInfo escortRoundInfo = bestEscortRoundInfoMap.get(config.getNowRound());
//                    if (escortRoundInfo != null) {
//                        for (Integer quality : biaoJuData.getBestQualityList()) {
//                            if (!canRandomHighQualityList.contains(quality)) {
//                                continue;
//                            }
//                            CrossBiaoJuBestEscortData bestEscortData = escortRoundInfo.randomPopOnceBestEscort(quality, userInfo.getUserData().getUserId());
//                            if (bestEscortData != null) {
//                                BiaoJuUserEscortInfo biaoJuUserEscortInfo = new BiaoJuUserEscortInfo();
//                                biaoJuUserEscortInfo.setBestEscortId(bestEscortData.getUniqueId());
//                                biaoJuUserEscortInfo.setEscortId(bestEscortData.getEscortId());
//                                biaoJuUserEscortInfo.setCityId(bestEscortData.getCityId());
//
//                                randomList.remove(0);//移除一个普通镖
//                                randomList.add(biaoJuUserEscortInfo);
//
//                                userInfo.resetGuaranteeRefreshCount();
//
//                                addLockBestEscortNotice(bestEscortData);
//                                break;
//                            }
//                        }
//                    }
//                }
//            }
//        }

        return randomList;
    }

    /**
     * 刷新玩家镖单
     *
     * @param userId
     * @return
     */
    public BiaoJuProto.BiaoJuRefreshEscortListRespMsg.Builder refreshUserWaitTakeList(long userId, boolean isCostGoods) {
        BiaoJuProto.BiaoJuRefreshEscortListRespMsg.Builder resp = BiaoJuProto.BiaoJuRefreshEscortListRespMsg.newBuilder();
        resp.setRet(0);
        resp.setIsRefreshBest(false);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        Map<Integer, Integer> escortResultMap = new HashMap<>();
        synchronized (userInfo) {
            if (userInfo.getRunEscortData() != null) {//押镖中
                return resp.setRet(GameErrorCode.E_BIAOJU_RUNNING_ESCORT);
            }

            refreshUserWaitTakeList(userInfo);

            resp.setRemainBestEscortCount(getRemainBestEscortCount());
            resp.setNextRefreshTime(config.getThisRoundEndTime());

            List<BiaoJuUserEscortInfo> waitTakeList = userInfo.getWaitTakeList();
            for (int i = 0; i < waitTakeList.size(); i++) {
                BiaoJuUserEscortInfo userEscortInfo = waitTakeList.get(i);
                BiaoJuProto.BiaoJuWaitTakeEscortTemp.Builder builder = BiaoJuProto.BiaoJuWaitTakeEscortTemp.newBuilder();
                builder.setEscortId(userEscortInfo.getEscortId());
                builder.setCityId(userEscortInfo.getCityId());
                builder.setId(i + 1);
                builder.setCityAddition(getCityRankAddition(userId));
                resp.addWaitTakeList(builder);

                escortResultMap.put(userEscortInfo.getEscortId(), userEscortInfo.getBestEscortId() > 0 ? 1 : 0);

                if (userEscortInfo.getBestEscortId() >0) {
                    resp.setIsRefreshBest(true);
                }
            }
        }

        CrossAutoLogMgr.add(new LogBiaoJuRefresh(activityId, unionGroup, userId, isCostGoods ? 1 : 0, escortResultMap));

        return resp;
    }

    private void refreshUserWaitTakeList(CrossBiaoJuUserInfo userInfo) {
        BiaoJuConfig config = getConfig();
        if (config == null) {
            return;
        }
        List<BiaoJuUserEscortInfo> waitTakeList = userInfo.getWaitTakeList();
        //先返还优质镖,再抽
        for (BiaoJuUserEscortInfo biaoJuUserEscortInfo : waitTakeList) {
            if (biaoJuUserEscortInfo.getBestEscortId() > 0) {
                CrossBiaoJuBestEscortRoundInfo escortRoundInfo = bestEscortRoundInfoMap.get(config.getNowRound());
                if (escortRoundInfo != null) {
                    escortRoundInfo.backBestEscort(biaoJuUserEscortInfo.getBestEscortId());
                }
            }
        }

        List<BiaoJuUserEscortInfo> randomList = randomUserWaitTakeEscortList(userInfo);
        userInfo.updateWaitTakeList(randomList);
    }

    /**
     * 接镖
     *
     * @param userId
     * @param id
     * @return
     */
    public BiaoJuProto.BiaoJuTakeEscortRespMsg.Builder takeEscort(long userId, int id) {
        BiaoJuProto.BiaoJuTakeEscortRespMsg.Builder resp = BiaoJuProto.BiaoJuTakeEscortRespMsg.newBuilder();
        resp.setRet(0);
        resp.setIsBest(false);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        synchronized (unionInfo) {
            if (userInfo.getRunEscortData() != null) {//押镖中
                return resp.setRet(GameErrorCode.E_BIAOJU_RUNNING_ESCORT);
            }

            List<BiaoJuUserEscortInfo> waitTakeList = userInfo.getWaitTakeList();
            if (id < 1 || id > waitTakeList.size()) {
                return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
            }

            BiaoJuUserEscortInfo userEscortInfo = waitTakeList.remove(id - 1);
            CrossBiaoJuUserRunEscortData runEscortData = new CrossBiaoJuUserRunEscortData(runEscortUniqueId.getAndIncrement(), activityId, userId, unionGroup,
                    userEscortInfo.getEscortId(), userEscortInfo.getCityId(), userEscortInfo.getBestEscortId(), config.getNowRound());
            runEscortData.setTakeTime(DateHelper.getCurrentTime());

            refreshRunEscortBattleValue(runEscortData);

            userInfo.setRunEscortData(runEscortData);

            //如果有优质单,返还优质单
            for (BiaoJuUserEscortInfo biaoJuUserEscortInfo : waitTakeList) {
                if (biaoJuUserEscortInfo.getBestEscortId() > 0) {
                    CrossBiaoJuBestEscortRoundInfo escortRoundInfo = bestEscortRoundInfoMap.get(config.getNowRound());
                    if (escortRoundInfo != null) {
                        escortRoundInfo.backBestEscort(biaoJuUserEscortInfo.getBestEscortId());
                    }
                }
            }

            userInfo.updateWaitTakeList(new ArrayList<>());

            BiaoJuDartConfig dartConfig = config.getDartConfig(userInfo.getRunEscortData().getEscortId());

            //默认尝试拉上次组队的队友
            CrossBiaoJuUserRunEscortData lastOneHistoryEscort = userInfo.getLastOneHistoryEscort();
            if (lastOneHistoryEscort != null) {
                for (BiaoJuTeamUserInfo biaoJuTeamUserInfo : lastOneHistoryEscort.getTeamUserList()) {
                    long teamUserId = biaoJuTeamUserInfo.getUserId();
                    CrossBiaoJuUserInfo teamUserInfo = getUserInfoOnlyGet(teamUserId);
                    if (teamUserInfo == null) {
                        continue;
                    }
                    if (!teamUserInfo.checkCanBePull(dartConfig.getGear(), userId)) {
                        continue;
                    }
                    if (!teamUserInfo.checkDayJoinNumLimit(config.getDayJoinLimit())) {
                        continue;
                    }

                    int ret = userInfo.addTeamUser(teamUserId, teamUserInfo.getUserData().getLevel(), config.getTeamJoinLimit());
                    if (ret == 0) {
                        teamUserInfo.addDayJoinNum();
                    }
                }
            }

            if (runEscortData.getBestEscortId() > 0) {
                addLockBestEscortNotice(runEscortData);
                resp.setIsBest(true);
            }
        }

        resp.setRemainBestEscortCount(getRemainBestEscortCount());
        resp.setNextRefreshTime(config.getThisRoundEndTime());
        resp.setEscortInfo(parseEscortDetail(userInfo.getRunEscortData(), userId));

        //通知同商会玩家
        BiaoJuProto.BiaoJuNewTakeEscortNotifyMsg.Builder syncMsg = BiaoJuProto.BiaoJuNewTakeEscortNotifyMsg.newBuilder();
        syncMsg.setActivityId(activityId);
        syncMsg.setEscortInfo(parseMemberEscortSimple(userInfo.getRunEscortData(), userId));
        syncUnionAllMemberMsg(userInfo.getUserData().getUnionId(), userId, ClientProtocol.U_BIAOJU_NEW_TAKE_ESCORT_NOTIFY, syncMsg);

        addNeedSyncUnion(unionInfo);

        return resp;
    }

    /**
     * 刷新押镖战斗力
     *
     * @param runEscortData
     */
    public int refreshRunEscortBattleValue(CrossBiaoJuUserRunEscortData runEscortData) {
        BiaoJuConfig config = getConfig();

        if (runEscortData.getBattleLogList().size() > 0) {//已经有战斗记录,不再刷新
            return runEscortData.getBattleValue();
        }

        int battleValue = 0;
        int level = getUserInfoOnlyGet(runEscortData.getUserId()).getUserData().getLevel();
        int titlePower = config.getTitlePower(level);
        battleValue += titlePower;

        BigInteger teamUserPower = BigInteger.ZERO;
        for (BiaoJuTeamUserInfo biaoJuTeamUserInfo : runEscortData.getTeamUserList()) {
            long userId = biaoJuTeamUserInfo.getUserId();
            CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
            if (userInfo != null) {
                teamUserPower = teamUserPower.add(BigInteger.valueOf(config.getTitlePower(userInfo.getUserData().getLevel())));
                biaoJuTeamUserInfo.setLevel(userInfo.getUserData().getLevel());
            }
        }
        int teamUserPowerEnd = teamUserPower.multiply(BigInteger.valueOf(config.getTeamUserBattleTransform())).divide(BigInteger.valueOf(1000)).intValue();

        battleValue += teamUserPowerEnd;

        if (battleValue != runEscortData.getBattleValue()) {
            runEscortData.setBattleValue(battleValue);
            runEscortData.setRemainBlood(battleValue);
        }

        return battleValue;
    }

    /**
     * 开始押镖
     *
     * @param userId
     * @return
     */
    public BiaoJuProto.BiaoJuStartEscortRespMsg.Builder startRunEscort(long userId) {
        BiaoJuProto.BiaoJuStartEscortRespMsg.Builder resp = BiaoJuProto.BiaoJuStartEscortRespMsg.newBuilder();
        resp.setRet(0);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        synchronized (unionInfo) {
            CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
            if (runEscortData == null) {
                return resp.setRet(GameErrorCode.E_BIAOJU_NOT_TAKE_ESCORT);
            }

            if (runEscortData.getRunStartTime() > 0) {
                return resp.setRet(GameErrorCode.E_BIAOJU_RUNNING_ESCORT);
            }

            runEscortData.setRunStartTime(DateHelper.getCurrentTime());
            runEscortData.setUserLevel(userInfo.getUserData().getLevel());
            runEscortData.setUnionLevel(unionInfo.getUnionData().getLevel());
            runEscortData.setCityAddition(getCityRankAddition(userInfo.getUserData().getUserId()));

            resp.setEscortInfo(parseEscortDetail(runEscortData, userId));
        }

        resp.setRemainBestEscortCount(getRemainBestEscortCount());
        resp.setNextRefreshTime(getConfig().getThisRoundEndTime());


        return resp;
    }

    /**
     * 加入或退出别人的镖
     *
     * @param userId
     * @param targetUserId
     * @param type         1-加入 2-退出
     * @return
     */
    public BiaoJuProto.BiaoJuJoinEscortRespMsg.Builder joinEscort(long userId, long targetUserId, int type) {
        BiaoJuProto.BiaoJuJoinEscortRespMsg.Builder resp = BiaoJuProto.BiaoJuJoinEscortRespMsg.newBuilder();
        resp.setRet(0);
        resp.setType(type);

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUserInfo targetUserInfo = getUserInfoOnlyGet(targetUserId);
        if (targetUserInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_ESCORT_NOT_FOUND);
        }

        if (!userInfo.getUserData().getUnionId().equals(targetUserInfo.getUserData().getUnionId())) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_SAME_UNION);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        checkUserRunEscortEnd(targetUserInfo);

        synchronized (unionInfo) {
            if (type == 1) {
                if (!userInfo.checkDayJoinNumLimit(config.getDayJoinLimit())) {
                    return resp.setRet(GameErrorCode.E_BIAOJU_DAY_JOIN_NUM_LIMIT);
                }
                int ret = targetUserInfo.addTeamUser(userId, userInfo.getUserData().getLevel(), config.getTeamJoinLimit());

                if (ret != 0) {
                    return resp.setRet(ret);
                }

                userInfo.addDayJoinNum();
            } else {
                int ret = targetUserInfo.removeTeamUser(userId);
                if (ret != 0) {
                    return resp.setRet(ret);
                }

                userInfo.decDayJoinNum();
            }

            CrossBiaoJuUserRunEscortData runEscortData = targetUserInfo.getRunEscortData();
            resp.setEscortInfo(parseEscortDetail(runEscortData, userId));
            refreshRunEscortBattleValue(runEscortData);
        }

        addNeedSyncUnion(unionInfo);

        return resp;
    }

    /**
     * 获取最佳镖列表
     *
     * @param userId
     * @return
     */
    public BiaoJuProto.BiaoJuBestEscortListRespMsg.Builder getBestEscortList(long userId, BiaoJuProto.BiaoJuBestEscortListReqMsg reqMsg) {
        BiaoJuProto.BiaoJuBestEscortListRespMsg.Builder resp = BiaoJuProto.BiaoJuBestEscortListRespMsg.newBuilder();
        resp.setRet(0);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuBestEscortRoundInfo bestEscortRoundInfo = bestEscortRoundInfoMap.get(config.getNowRound());
        if (bestEscortRoundInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_BEST_ESCORT);
        }

        List<CrossBiaoJuBestEscortData> resultList = bestEscortRoundInfo.getBestEscortList();
        for (CrossBiaoJuBestEscortData bestEscortData : resultList) {
            BiaoJuProto.BiaoJuBestEscortTemp.Builder builder = BiaoJuProto.BiaoJuBestEscortTemp.newBuilder();
            builder.setQuality(bestEscortData.getQuality());
            builder.setNowNum(bestEscortData.getRemainNum());
            builder.setMaxNum(bestEscortData.getTotalNum());

            resp.addBestEscortList(builder);
        }

        resp.setRemainBestEscortCount(getRemainBestEscortCount());
        resp.setNextRefreshTime(getConfig().getThisRoundEndTime());

        return resp;
    }

    public BiaoJuProto.BiaoJuCityTemp.Builder parseCityTemp(CrossBiaoJuCityData cityData) {
        BiaoJuProto.BiaoJuCityTemp.Builder temp = BiaoJuProto.BiaoJuCityTemp.newBuilder();
        temp.setCityId(cityData.getCityId());
        temp.setCityScore(cityData.getScore());
        temp.setLastCityRank(cityData.getLastRank());
        long roundScore = cityData.getRoundScore();
        if (roundScore == 0) {
            roundScore = cityData.getHistoryRoundScore(getConfig().getNowRound());
        }
        temp.setNowRoundScore(roundScore);
        return temp;
    }

    /**
     * 固定时间更新城市排行
     */
    public void updateCityRankInfo() {
        for (BiaoJuCityConfig cityConfig : getConfig().getCityConfigMap().values()) {
            CrossBiaoJuCityRankInfo cityRankInfo = cityRankInfoMap.get(cityConfig.getId());
            if (cityRankInfo == null) {
                continue;
            }
            cityRankInfo.sortCityRank();
        }
    }

    /**
     * 获取城市排行
     *
     * @param userId
     * @param cityId
     * @return
     */
    public BiaoJuProto.BiaoJuCityUnionRankRespMsg.Builder getCityRankList(long userId, int cityId) {
        BiaoJuProto.BiaoJuCityUnionRankRespMsg.Builder resp = BiaoJuProto.BiaoJuCityUnionRankRespMsg.newBuilder();
        resp.setRet(0);
        resp.setCityId(cityId);

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuCityRankInfo cityRankInfo = cityRankInfoMap.get(cityId);
        if (cityRankInfo == null) {
            return resp;
        }

        List<CrossBiaoJuCityData> cityDataList = cityRankInfo.getCityDataList();
        for (int i = 0; i < cityDataList.size(); i++) {
            CrossBiaoJuCityData cityData = cityDataList.get(i);
            BiaoJuProto.BiaoJuCityUnionRankTemp.Builder temp = BiaoJuProto.BiaoJuCityUnionRankTemp.newBuilder();
            temp.setLastRank(cityData.getLastRank());
            temp.setUnionScore(cityData.getRankScore());
            CrossBiaoJuUnionInfo unionInfo = getUnionInfo(cityData.getUnionId());
            temp.setUnionInfo(parseUnionTemp(unionInfo));
            temp.setLastRankScore(cityData.getLastRankScore());
            long roundScore = cityData.getRoundScore();
            if (roundScore == 0) {
                roundScore = cityData.getHistoryRoundScore(getConfig().getNowRound());
            }
            temp.setRoundScore(roundScore);

            resp.addRankList(temp);
        }

        return resp;
    }

    /**
     * 获得商会成员的走镖列表
     *
     * @param userId
     * @return
     */
    public BiaoJuProto.BiaoJuMapUnionMemberEscortListRespMsg.Builder getUnionMemberEscortList(long userId) {
        BiaoJuProto.BiaoJuMapUnionMemberEscortListRespMsg.Builder resp = BiaoJuProto.BiaoJuMapUnionMemberEscortListRespMsg.newBuilder();
        resp.setRet(0);

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        List<CrossBiaoJuUserInfo> memberInfoList = unionInfo.getMemberInfoList();
        for (CrossBiaoJuUserInfo biaoJuUserInfo : memberInfoList) {
            CrossBiaoJuUserRunEscortData runEscortData = biaoJuUserInfo.getRunEscortData();
            if (runEscortData == null) {
                continue;
            }

            BiaoJuProto.BiaoJuMemberEscortDetailTemp.Builder builder = parseEscortDetail(runEscortData, userId);
            resp.addEscortList(builder);
        }

        for (CrossBiaoJuCityRankInfo cityRankInfo : cityRankInfoMap.values()) {
            String lastFirstUnionId = cityRankInfo.getLastFirstUnionId();
            if (lastFirstUnionId == null) {
                continue;
            }

            CrossBiaoJuUnionInfo cityUnionInfo = getUnionInfo(lastFirstUnionId);
            if (cityUnionInfo == null) {
                continue;
            }
            BiaoJuProto.BiaoJuCityFirstUnionTemp.Builder cityBuilder = BiaoJuProto.BiaoJuCityFirstUnionTemp.newBuilder();
            cityBuilder.setCityId(cityRankInfo.getCityId());
            cityBuilder.setUnionInfo(parseUnionTemp(cityUnionInfo));
            resp.addCityFirstUnion(cityBuilder);
        }
        return resp;
    }

    /**
     * 获得商会的城市列表
     *
     * @param userId
     * @return
     */
    public BiaoJuProto.BiaoJuCityListRespMsg.Builder getUnionCityList(long userId) {
        BiaoJuProto.BiaoJuCityListRespMsg.Builder resp = BiaoJuProto.BiaoJuCityListRespMsg.newBuilder();
        resp.setRet(0);

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        for (CrossBiaoJuCityData cityData : unionInfo.getCityDataList()) {
            resp.addCityList(parseCityTemp(cityData));
        }

        return resp;
    }

    /**
     * 城市建设
     */
    public BiaoJuProto.BiaoJuCityBuildRespMsg.Builder buildCity(long userId, int cityId, long num) {
        BiaoJuProto.BiaoJuCityBuildRespMsg.Builder resp = BiaoJuProto.BiaoJuCityBuildRespMsg.newBuilder();
        resp.setRet(0);
        resp.setNum(num);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        long currentTime = DateHelper.getCurrentTime();
        if (currentTime >= config.getNowCityRankSettleTime()) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CITY_RANK_IN_SETTLE);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuCityData cityData = unionInfo.getCityDataMap().get(cityId);
        if (cityData == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CITY_NOT_FOUND);
        }

        synchronized (userInfo) {
            if (userInfo.getUserData().getMoney() >= num) {
                userInfo.getUserData().setMoney(userInfo.getUserData().getMoney() - num);
            } else {
                return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ENOUGH_MONEY);
            }
        }

        synchronized (unionInfo) {
            cityData.setScore(cityData.getScore() + num);
            cityData.setRoundScore(cityData.getRoundScore() + num);
            cityData.setScoreChangeTime(currentTime);
            cityData.memberAddScore(config.getNowRound(), userInfo.getUserData().getUserId(), num, DateHelper.getCurrentTime());

            resp.setCityId(cityId);
            resp.setCityScore(cityData.getScore());
        }

        //奖励
        Property expReward = config.getCityBuildReward();
        expReward.goodCountMultiNum(num);

        Property totalReward = new Property();
        totalReward.addProperty(expReward);

        BigInteger unionExp = totalReward.getCountByGoodsId(config.getPrestigeGoodsId()); //获得的商会经验
        unionInfo.addExp(unionExp.longValue(), config);

        userInfo.addUnionExp(unionExp.longValue());

        resp.setReward(totalReward.toHelperString());
        resp.setUnionInfo(parseUnionTemp(unionInfo));
        resp.setUserInfo(parseUserTemp(userInfo));

        CrossBiaoJuCityRankInfo cityRankInfo = cityRankInfoMap.get(cityId);
        if (cityRankInfo != null) {
            cityRankInfo.sortCityRank();
        }

        unionRankChanged.set(true);

        addNeedSyncUnion(unionInfo);

        CrossAutoLogMgr.add(new LogBiaoJuBuildCity(activityId, unionGroup, userId,
                unionInfo.getUnionData().getUnionId(), unionInfo.getUnionData().getLevel(), unionExp.intValue(), unionInfo.getUnionData().getExp(),
                cityId, num, resp.getReward(), num, cityData.getScore()));

        return resp;
    }

    /**
     * 加速押镖
     *
     * @param userId
     * @param count      使用的道具数
     * @param perSpeedUp 每个道具加速的时间
     * @return
     */
    public BiaoJuProto.BiaoJuSpeedupEscortRespMsg.Builder speedUpEscort(long userId, int count, long perSpeedUp) {
        BiaoJuProto.BiaoJuSpeedupEscortRespMsg.Builder resp = BiaoJuProto.BiaoJuSpeedupEscortRespMsg.newBuilder();
        resp.setRet(0);
        resp.setNum(count);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        checkUserRunEscortEnd(userInfo);

        CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
        if (runEscortData == null) {
            return resp.setRet(GameErrorCode.E_BIAOJU_ESCORT_NOT_FOUND);
        }

        synchronized (userInfo) {
            if (runEscortData.getRunStartTime() == 0) {
                return resp.setRet(GameErrorCode.E_BIAOJU_ESCORT_NOT_RUN);
            }

            if (runEscortData.getFinishTime() > 0) {
                return resp.setRet(GameErrorCode.E_BIAOJU_ESCORT_FINISHED);
            }

            //原定结束时间
            long endTime = runEscortData.getRunStartTime() + config.getEscortMinSecondMillions();
            endTime = endTime - runEscortData.getSpeedUpTime();

            if (DateHelper.getCurrentTime() >= endTime) {
                return resp.setRet(GameErrorCode.E_BIAOJU_ESCORT_FINISHED);
            }

            //算一下最大消耗数量,向上取整
            long maxSpeedUpTime = endTime - DateHelper.getCurrentTime();
            long maxSpeedUpCount = (maxSpeedUpTime + perSpeedUp - 1) / perSpeedUp;
            int realUseNum = (int) Math.min(count, maxSpeedUpCount);
            resp.setRealUseNum(realUseNum);

            //加速时间
            long speedUpTime = realUseNum * perSpeedUp;
            runEscortData.setSpeedUpTime(runEscortData.getSpeedUpTime() + speedUpTime);
        }

        checkUserRunEscortEnd(userInfo);

        resp.setSpeedUpTime(runEscortData.getSpeedUpTime());
        resp.setEscortInfo(parseEscortDetail(runEscortData, userId));

        return resp;
    }

    /**
     * 自动开始押镖检测
     */
    public void autoStartRunEscortCheck(CrossBiaoJuUserInfo userInfo) {
        BiaoJuConfig config = getConfig();
        if (config == null) {
            return;
        }

        CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
        if (runEscortData == null) {
            return;
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return;
        }

        if (runEscortData.getRunStartTime() > 0) {
            return;
        }

        long currentTime = DateHelper.getCurrentTime();
        long passTime = currentTime - runEscortData.getTakeTime();
        if (passTime >= config.getPrepareTimeSecondMillions()) {
            synchronized (userInfo) {
                runEscortData.setRunStartTime(runEscortData.getTakeTime() + config.getPrepareTimeSecondMillions());
                runEscortData.setUserLevel(userInfo.getUserData().getLevel());
                runEscortData.setUnionLevel(unionInfo.getUnionData().getLevel());
                runEscortData.setCityAddition(getCityRankAddition(runEscortData.getUserId()));
            }
        }
    }

    /**
     * 押镖结束给赏金和个人经验
     *
     * @param userInfo
     */
    public void checkUserRunEscortEnd(CrossBiaoJuUserInfo userInfo) {
        if (userInfo == null) {
            return;
        }

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return;
        }


        CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
        if (runEscortData == null) {
            return;
        }

        BiaoJuDartConfig dartConfig = config.getDartConfig(runEscortData.getEscortId());
        if (dartConfig == null) {
            return;
        }

        if (runEscortData.getRunStartTime() == 0) {
            return;
        }

        if (runEscortData.getFinishTime() > 0) {
            BiaoJuRunResult biaoJuRunReward = userInfo.endRunEscort(config, getUnionInfo(userInfo.getUserData().getUnionId()));
            for (BiaoJuTeamUserInfo biaoJuTeamUserInfo : runEscortData.getTeamUserList()) {
                CrossBiaoJuUserInfo teamUserInfo = getUserInfoOnlyGet(biaoJuTeamUserInfo.getUserId());
                if (teamUserInfo != null) {
                    teamUserInfo.addRunReward(biaoJuRunReward, config, false);
                    addNeedSyncUser(biaoJuTeamUserInfo.getUserId());
                }
            }
            userRankChanged.set(true);
            syncEscortFinish(runEscortData.getUserId());
            return;
        }

        long currentTime = DateHelper.getCurrentTime();
        long passTime = currentTime - runEscortData.getRunStartTime() + runEscortData.getSpeedUpTime(); //已经花费的时间
        long totalTime = config.getEscortMinSecondMillions(); //总时间

        synchronized (userInfo) {
            boolean isLose = false;
            //检查战斗
            for (int i = 0; i < dartConfig.getMonsterTimeList().size(); i++) {
                //怪物出现的时间点,千分比
                int timePoint = dartConfig.getMonsterTimeList().get(i);
                int monsterPower = dartConfig.getMonsterPowerList().get(i);

                long checkTime = BigDecimal.valueOf(timePoint).divide(BigDecimal.valueOf(1000), 3, RoundingMode.UP).multiply(BigDecimal.valueOf(totalTime)).longValue();
                if (passTime >= checkTime) {//经过了战斗地点,进行战斗
                    /**
                     * 1	劫匪的波次、和对应波次的位置&强度均是跟随镖单生成时既定的
                     * 2	战力pk
                     **1	若当前波次劫匪战力小于等于镖队战力，击退，损耗为0
                     **2	若当前劫匪战力大于镖队战力，
                     ***1	损耗行为为概率事件，失败概率为镖队战力/劫匪战力
                     ***2	损失血量=劫匪战力-镖队战力
                     * 3	劫镖结果预设
                     **1	镖队英勇无比，无任何损失
                     **2	对方实力强劲，损失n%
                     **3	虽然对方实力强劲，但未知原因撤退了，无任何损失
                     */
                    //                劫镖结果预设
//                1	镖队英勇无比，无任何损失
//                2	对方实力强劲，损失n%
//                3	虽然对方实力强劲，但未知原因撤退了，无任何损失

                    refreshRunEscortBattleValue(runEscortData);

                    int logSize = runEscortData.getBattleLogList().size();
                    if (logSize > i) {
                        //有失败的点,后面都是失败的
                        isLose = runEscortData.getBattleLogList().get(i).getResult() == 2;
                        continue;
                    }

                    BiaoJuEscortBattleLog biaoJuEscortBattleLog = new BiaoJuEscortBattleLog();
                    biaoJuEscortBattleLog.setBattleTime(currentTime);
                    biaoJuEscortBattleLog.setBattleValue(runEscortData.getBattleValue());
                    biaoJuEscortBattleLog.setRemainBlood(runEscortData.getRemainBlood());
                    biaoJuEscortBattleLog.setEventId(config.randomOnceEventId());
                    biaoJuEscortBattleLog.setDecBlood(0);

                    if (runEscortData.getBattleValue() >= monsterPower && !isLose) {
                        //击退，损耗为0
                        biaoJuEscortBattleLog.setResult(1);
                    } else {
                        //损耗行为为概率事件，失败概率为镖队战力/劫匪战力
                        int randomCheckValue = BigDecimal.valueOf(runEscortData.getBattleValue()).divide(BigDecimal.valueOf(monsterPower), 3, RoundingMode.UP).multiply(BigDecimal.valueOf(1000)).intValue();
                        boolean isWin = config.calcBattleWin(randomCheckValue);
                        if (isLose || !isWin) {//需求修改,没有血量的概念,判定失败就是失败了
//                            //损失血量=劫匪战力-镖队战力
//                            int loseValue = monsterPower - runEscortData.getBattleValue();
//                            runEscortData.setRemainBlood(runEscortData.getRemainBlood() - loseValue);

                            biaoJuEscortBattleLog.setDecBlood(monsterPower);
                            biaoJuEscortBattleLog.setRemainBlood(0);
                            biaoJuEscortBattleLog.setResult(2);

                            isLose = true;
                        } else {
                            biaoJuEscortBattleLog.setResult(3);
                        }
                    }
                    runEscortData.getBattleLogList().add(biaoJuEscortBattleLog);
                }

//                if (isLose) {//有失败的点,后面都是失败的
//                    if (runEscortData.getBattleLogList().size() < i + 1) {
//                        BiaoJuEscortBattleLog biaoJuEscortBattleLog = new BiaoJuEscortBattleLog();
//                        biaoJuEscortBattleLog.setBattleTime(currentTime);
//                        biaoJuEscortBattleLog.setBattleValue(runEscortData.getBattleValue());
//                        biaoJuEscortBattleLog.setRemainBlood(runEscortData.getRemainBlood());
//                        biaoJuEscortBattleLog.setEventId(config.randomOnceEventId());
//                        biaoJuEscortBattleLog.setDecBlood(0);
//                        biaoJuEscortBattleLog.setRemainBlood(0);
//                        biaoJuEscortBattleLog.setResult(2);
//                        runEscortData.getBattleLogList().add(biaoJuEscortBattleLog);
//                    }
//                }
            }
        }

        if (passTime >= totalTime) {
            BiaoJuRunResult biaoJuRunReward = userInfo.endRunEscort(config, getUnionInfo(userInfo.getUserData().getUnionId()));
            for (BiaoJuTeamUserInfo biaoJuTeamUserInfo : runEscortData.getTeamUserList()) {
                CrossBiaoJuUserInfo teamUserInfo = getUserInfoOnlyGet(biaoJuTeamUserInfo.getUserId());
                if (teamUserInfo != null) {
                    teamUserInfo.addRunReward(biaoJuRunReward, config, false);
                    addNeedSyncUser(biaoJuTeamUserInfo.getUserId());
                }
            }
            userRankChanged.set(true);

            syncEscortFinish(runEscortData.getUserId());
        }
    }

    private void syncEscortFinish(long userId) {
        BiaoJuProto.BiaoJuNewFinishEscortNotifyMsg.Builder syncMsg = BiaoJuProto.BiaoJuNewFinishEscortNotifyMsg.newBuilder();
        syncMsg.setActivityId(activityId);
        syncMsg.setTargetUserId(userId);

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return;
        }

        syncUnionAllMemberMsg(userInfo.getUserData().getUnionId(), 0, ClientProtocol.U_BIAOJU_NEW_FINISH_ESCORT_NOTIFY, syncMsg);

        syncUserData(userId);
    }

    public void syncUserData(long userId) {
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return;
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return;
        }

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return;
        }

        BiaoJuProto.BiaoJuUserDataCrossBackSyncMsg.Builder syncMsg = BiaoJuProto.BiaoJuUserDataCrossBackSyncMsg.newBuilder();
        syncMsg.setActivityId(activityId);
        syncMsg.setMoney(userInfo.getUserData().getMoney());
        syncMsg.setUserExp(userInfo.getUserData().getExp());
        syncMsg.setUnionExp(unionInfo.getUnionData().getExp());
        syncMsg.setCanJoin(0);

        if (userInfo.checkDayJoinNumLimit(getConfig().getDayJoinLimit())) {//有次数参加
            List<CrossBiaoJuUserInfo> memberInfoList = unionInfo.getMemberInfoList();
            for (CrossBiaoJuUserInfo biaoJuUserInfo : memberInfoList) {
                if (biaoJuUserInfo.targetCanJoin(userId, config.getTeamJoinLimit()) == 0) {
                    syncMsg.setCanJoin(1);
                    break;
                }
            }
        }

        MessageHelper.sendPacket(CrossUserMgr.getServerIdByUserId(userId), userId,
                YanQuMessageUtils.buildMessage(GameProtocol.S_BIAOJU_USER_DATA_CROSS_BACK, syncMsg));
    }

    private void syncUnionAllMemberMsg(String unionId, long excludeUserId, int code, AbstractMessage.Builder<?> messageBuilder) {
        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(unionId);
        if (unionInfo == null) {
            return;
        }
        List<Long> userIds = new ArrayList<>();
        List<CrossBiaoJuUserInfo> memberInfoList = unionInfo.getMemberInfoList();
        for (CrossBiaoJuUserInfo biaoJuUserInfo : memberInfoList) {
            if (biaoJuUserInfo.getUserData().getUserId() == excludeUserId) {
                continue;
            }
            userIds.add(biaoJuUserInfo.getUserData().getUserId());
        }


        MessageHelper.sendPacketToAll(code, messageBuilder, userIds);
    }

    private void syncAllUserMsg(long excludeUserId, int code, AbstractMessage.Builder<?> messageBuilder) {
        List<CrossBiaoJuUserInfo> userInfoList = getUserInfoList();
        List<Long> userIds = new ArrayList<>();
        for (CrossBiaoJuUserInfo biaoJuUserInfo : userInfoList) {
            if (biaoJuUserInfo.getUserData().getUserId() == excludeUserId) {
                continue;
            }
            userIds.add(biaoJuUserInfo.getUserData().getUserId());
        }
        MessageHelper.sendPacketToAll(code, messageBuilder, userIds);
    }

    /**
     * 踢队友
     *
     * @param userId
     * @param targetUserId
     * @return
     */
    public BiaoJuProto.BiaoJuKickTeamUserRespMsg.Builder kickTeamUser(long userId, long targetUserId) {
        BiaoJuProto.BiaoJuKickTeamUserRespMsg.Builder respMsg = BiaoJuProto.BiaoJuKickTeamUserRespMsg.newBuilder();
        respMsg.setRet(0);

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        checkUserRunEscortEnd(userInfo);

        CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
        if (runEscortData == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_TAKE_ESCORT);
        }

        if (runEscortData.getRunStartTime() > 0) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_RUNNING_ESCORT);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        synchronized (unionInfo) {
            int ret = userInfo.removeTeamUser(targetUserId);
            if (ret != 0) {
                return respMsg.setRet(ret);
            }

            CrossBiaoJuUserInfo targetUserInfo = getUserInfoOnlyGet(targetUserId);
            if (targetUserInfo == null) {
                return respMsg.setRet(GameErrorCode.E_BIAOJU_TARGET_NOT_ABLE);
            }
            targetUserInfo.decDayJoinNum();

            refreshRunEscortBattleValue(runEscortData);
        }

        respMsg.setEscortInfo(parseEscortDetail(runEscortData, userId));

        return respMsg;
    }

    /**
     * 缓存个人榜商会榜
     */
    public void rankSortTask() {
        if (userRankChanged.compareAndSet(true, false)) {
            updateUserRankBuilder();
        }

        if (unionRankChanged.compareAndSet(true, false)) {
            updateUnionRankBuilder();
        }

        refreshUnionPosition();
    }

    public int getCityRank(CrossBiaoJuUserInfo userInfo, int cityId) {
        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return 0;
        }
        CrossBiaoJuCityData cityData = unionInfo.getCityDataMap().get(cityId);
        if (cityData == null) {
            return 0;
        }
        return cityData.getLastRank();
    }

    public UnionActivityRankProto.UnionActivityRankListMsg getUnionRankBuild() {
        synchronized (unionRankBuilder) {
            return unionRankBuilder.build();
        }
    }

    public RankProto.RankListMsg getUserRankBuild() {
        synchronized (userRankBuilder) {
            return userRankBuilder.build();
        }
    }

    public void updateUserRankBuilder() {
        List<CrossBiaoJuUserInfo> userInfoList = getUserInfoList();
        for (CrossBiaoJuUserInfo biaoJuUserInfo : userInfoList) {
            biaoJuUserInfo.refreshRankParam();
        }

        userInfoList.sort((o1, o2) -> {
            int compare = Long.compare(o2.getRankScore(), o1.getRankScore());
            if (compare == 0) {
                compare = Long.compare(o1.getScoreChangeTime(), o2.getScoreChangeTime());
            }
            return compare;
        });

        RankProto.RankListMsg.Builder rankBuilder = RankProto.RankListMsg.newBuilder();

        int maxRank = 0;
        List<ActivityConditionInfo> conditionInfoList = ActivityInfoMgr.getConditionInfoList(activityId, eGamePlayerEventType.BiaoJuExpRank.getValue());
        if (conditionInfoList != null) {
            maxRank = ActivityHelper.getMaxRank(conditionInfoList);
        }
        if (maxRank <= 0) {
            maxRank = GameConfig.RANK_DEFAULT_MAX_COUNT;
        }

        for (int i = 0; i < userInfoList.size(); i++) {
            int rank = i + 1;
            CrossBiaoJuUserInfo biaoJuUserInfo = userInfoList.get(i);
            if (biaoJuUserInfo.getRankScore() == 0) {
                break;
            }
            biaoJuUserInfo.setRank(rank);

            if (i < maxRank) {
                RankProto.RankTempMsg.Builder builder = RankProto.RankTempMsg.newBuilder();
                builder.setValue(String.valueOf(biaoJuUserInfo.getRankScore()));
                builder.setUserId(biaoJuUserInfo.getUserData().getUserId());
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(biaoJuUserInfo.getUserData().getUserId());
                builder.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));

                rankBuilder.addRankList(builder);
            }
        }
        synchronized (userRankBuilder) {
            this.userRankBuilder = rankBuilder;
        }
    }

    public void updateUnionRankBuilder() {
        List<CrossBiaoJuUnionInfo> unionInfoList = getUnionInfoList();

        for (CrossBiaoJuUnionInfo biaoJuUnionInfo : unionInfoList) {
            biaoJuUnionInfo.refreshRankParam();
        }

        unionInfoList.sort((o1, o2) -> {
            int compare = Long.compare(o2.getRankScore(), o1.getRankScore());
            if (compare == 0) {
                compare = Long.compare(o1.getScoreChangeTime(), o2.getScoreChangeTime());
            }
            return compare;
        });

        UnionActivityRankProto.UnionActivityRankListMsg.Builder rankBuilder = UnionActivityRankProto.UnionActivityRankListMsg.newBuilder();

        int maxRank = 0;
        List<ActivityConditionInfo> conditionInfoList = ActivityInfoMgr.getConditionInfoList(activityId, eGamePlayerEventType.BiaoJuUnionExpRank.getValue());
        if (conditionInfoList != null) {
            maxRank = ActivityHelper.getMaxRank(conditionInfoList);
        }
        if (maxRank <= 0) {
            maxRank = GameConfig.RANK_DEFAULT_MAX_COUNT;
        }

        for (int i = 0; i < unionInfoList.size(); i++) {
            int rank = i + 1;
            CrossBiaoJuUnionInfo biaoJuUnionInfo = unionInfoList.get(i);
            if (biaoJuUnionInfo.getRankScore() == 0l) {//0分不上榜
                break;
            }
            biaoJuUnionInfo.setRank(rank);

            if (i < maxRank) {
                UnionActivityRankProto.UnionActivityRankTempMsg.Builder builder = UnionActivityRankProto.UnionActivityRankTempMsg.newBuilder();
                builder.setUnionUid(biaoJuUnionInfo.getUnionData().getUnionId());
                UnionActivityGroupUnion unionData = Cross2UnionActivityGroupMgr.getUnionData(activityId, biaoJuUnionInfo.getUnionData().getUnionId(), unionGroup);
                builder.setUnionBaseData(UnionBasePb.parseUnionBaseTempMsg(unionData.getUnionBaseInfo()));
                builder.setValue(String.valueOf(biaoJuUnionInfo.getRankScore()));

                rankBuilder.addRankList(builder);
            }
        }

        synchronized (unionRankBuilder) {
            this.unionRankBuilder = rankBuilder;
        }
    }

    public void sendUserRankList(long userId, long serverId) {
        RankProto.RankListMsg rankBuild = getUserRankBuild();

        int myRank = -1;
        for (int i = 0; i < rankBuild.getRankListList().size(); i++) {
            RankProto.RankTempMsg rankTempMsg = rankBuild.getRankListList().get(i);
            if (rankTempMsg.getUserId() == userId) {
                myRank = i + 1;
                break;
            }
        }

        CommonActivityProto.CommonActivityRankListRespMsg.Builder builder = CommonActivityProto.CommonActivityRankListRespMsg.newBuilder();
        builder.setMyRank(myRank);
        builder.setRankList(rankBuild);
        YanQuMessage message = YanQuMessageUtils.buildMessage(Protocol.U_ACTIVITY_RANK_LIST, builder);
        MessageHelper.sendPacket(serverId, userId, message);
    }

    public void sendUserRank(long userId, long serverId) {
        RankProto.RankListMsg rankBuild = getUserRankBuild();
        int myRank = -1;
        long myValue = 0;
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo != null) {
            myRank = userInfo.getUserData().getRank();
            if (myRank > rankBuild.getRankListCount()) {
                myRank = -1;
            }
            myValue = userInfo.getRankScore();
        }
        RankProto.CrossActivityUserRankRespMsg.Builder msg = RankProto.CrossActivityUserRankRespMsg.newBuilder();
        msg.setRank(myRank);
        msg.setValue(String.valueOf(myValue));
        YanQuMessage message = YanQuMessageUtils.buildMessage(ClientProtocol.U_CROSS_ACTIVITY_USER_RANK, msg);
        MessageHelper.sendPacket(serverId, userId, message);
    }

    public void getUserRankReward(long userId, long serverId, int conditionId) {
        int myRank = -1;
        long myValue = 0;
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo != null && userInfo.getUserData().getRank() > 0) {
            myRank = userInfo.getUserData().getRank();
            myValue = userInfo.getRankScore();
        }

        CrossActivityProto.CrossActivityGetRewardRespMsg.Builder respMsg = CrossActivityProto.CrossActivityGetRewardRespMsg.newBuilder();
        respMsg.setActivityId(activityId);
        respMsg.setConditionId(conditionId);
        respMsg.setRank(myRank);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_ACTIVITY_GET_RANK_REWARD_NOTIFY, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    public void sendUnionRankList(long userId, long serverId) {
        int myRank = -1;
        long myValue = 0;
        UnionActivityRankProto.UnionActivityRankListMsg unionRankBuild = getUnionRankBuild();

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo != null) {
            CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
            if (unionInfo != null) {
                myRank = unionInfo.getUnionData().getRank();
                if (myRank > unionRankBuild.getRankListCount()) {
                    myRank = -1;
                }
                myValue = unionInfo.getRankScore();
            }
        }

        StrongholdWarProto.StrongholdActivityUnionRankListRespMsg.Builder builder = StrongholdWarProto.StrongholdActivityUnionRankListRespMsg.newBuilder();
        builder.setMyRank(myRank);
        builder.setValue(String.valueOf(myValue));
        builder.setRankList(unionRankBuild);

        YanQuMessage message = YanQuMessageUtils.buildMessage(ClientProtocol.U_CROSS_GENERAL_ACTIVITY_UNION_RANK_LIST, builder);
        MessageHelper.sendPacket(serverId, userId, message);
    }

    public void sendUnionRank(long userId, long serverId) {
        UnionActivityRankProto.UnionActivityRankListMsg unionRankBuild = getUnionRankBuild();

        int myRank = -1;
        long myValue = 0;
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo != null) {
            CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
            if (unionInfo != null) {
                myRank = unionInfo.getUnionData().getRank();
                if (myRank > unionRankBuild.getRankListCount()) {
                    myRank = -1;
                }
                myValue = unionInfo.getRankScore();
            }
        }
        StrongholdWarProto.StrongholdActivityUnionRankListRespMsg.Builder msg = StrongholdWarProto.StrongholdActivityUnionRankListRespMsg.newBuilder();
        msg.setMyRank(myRank);
        msg.setValue(String.valueOf(myValue));
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(ClientProtocol.U_CROSS_GENERAL_ACTIVITY_UNION_RANK, msg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    public void getUnionRankReward(long userId, long serverId, int conditionId) {
        int myRank = -1;
        long myValue = 0;
        String unionUid = "";
        int position = eUnionPosition.Member.getValue();
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo != null) {
            CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
            if (unionInfo != null && unionInfo.getUnionData().getRank() > 0) {
                myRank = unionInfo.getUnionData().getRank();
                myValue = unionInfo.getRankScore();
                unionUid = unionInfo.getUnionData().getUnionId();
            }
        }

        UnionActivityGroupUnion unionData = Cross2UnionActivityGroupMgr.getUnionData(activityId, unionUid, unionGroup);
        if (unionData != null) {
            UnionActivityGroupUser activityGroupUser = unionData.getUserMap().get(userId);
            if (activityGroupUser != null) {
                position = activityGroupUser.getPosition();
            }
        }

        CrossActivityProto.CrossGeneralActivityGetRewardRespMsg.Builder respMsg = CrossActivityProto.CrossGeneralActivityGetRewardRespMsg.newBuilder();
        respMsg.setActivityId(activityId);
        respMsg.setConditionType(eGamePlayerEventType.BiaoJuUnionExpRank.getValue());
        respMsg.setConditionId(conditionId);
        respMsg.setRank(myRank);
        respMsg.setPosition(position);
        respMsg.setUnionUid(unionUid);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_GENERAL_ACTIVITY_GET_UNION_RANK_REWARD_NOTIFY, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    public int getUserGuaranteeRefreshCount(long userId) {
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo != null) {
            return userInfo.getUserData().getGuaranteeAmount();
        }
        return 0;
    }

    /**
     * 跨天重置,目前就城市积分需要跨天重置
     */
    public void dayReset() {
        long currentTime = DateHelper.getCurrentTime();
        if (DateHelper.isSameDay(currentTime / 1000, lastCheckTime / 1000)) {
            return;
        }
        lastCheckTime = currentTime;

        List<CrossBiaoJuUnionInfo> unionInfoList = getUnionInfoList();

        //城市积分跨天重置
        for (CrossBiaoJuUnionInfo biaoJuUnionInfo : unionInfoList) {
            for (CrossBiaoJuCityData biaoJuCityData : biaoJuUnionInfo.getCityDataList()) {
                if (DateHelper.isSameDay(currentTime / 1000, biaoJuCityData.getScoreChangeTime() / 1000)) {
                    continue;
                }

                biaoJuCityData.setScore(0);
                biaoJuCityData.setScoreChangeTime(currentTime);
                biaoJuCityData.setRoundScore(0);
                biaoJuCityData.setRankScore(0);
                biaoJuCityData.setRankTime(0);
            }
        }

        List<CrossBiaoJuUserInfo> userInfoList = getUserInfoList();

        for (CrossBiaoJuUserInfo biaoJuUserInfo : userInfoList) {
            biaoJuUserInfo.dayReset();
        }
    }

    public BiaoJuProto.BiaoJuSetCanBePullQualityRespMsg.Builder setCanBePullQuality(long userId, List<Integer> qualityList, List<Long> canBePullId, int qualitySwitch) {
        BiaoJuProto.BiaoJuSetCanBePullQualityRespMsg.Builder respMsg = BiaoJuProto.BiaoJuSetCanBePullQualityRespMsg.newBuilder();
        respMsg.setRet(0);

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        List<Long> unionUserList = Cross2UnionActivityGroupMgr.getUnionUserList(activityId, userInfo.getUserData().getUnionId());
        for (Long targetUserId : canBePullId) {
            if (targetUserId == userId) {
                return respMsg.setRet(GameErrorCode.E_BIAOJU_ESCORT_NOT_PULL_SELF);
            }
            if (!unionUserList.contains(targetUserId)) {
                return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_SAME_UNION);
            }
        }

        userInfo.setCanBePullQuality(qualityList, canBePullId, qualitySwitch);

        respMsg.addAllQuality(userInfo.getUserData().getCanBePullQuality());
        respMsg.addAllCanBePullId(userInfo.getUserData().getCanPullId());
        respMsg.setQualitySwitch(qualitySwitch);

        return respMsg;
    }

    public BiaoJuProto.BiaoJuGetCanBePullListRespMsg.Builder getCanBePullList(long userId) {
        BiaoJuProto.BiaoJuGetCanBePullListRespMsg.Builder respMsg = BiaoJuProto.BiaoJuGetCanBePullListRespMsg.newBuilder();
        respMsg.setRet(0);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
        if (runEscortData == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_TAKE_ESCORT);
        }

        BiaoJuDartConfig dartConfig = config.getDartConfig(runEscortData.getEscortId());
        if (dartConfig == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        List<CrossBiaoJuUserInfo> memberInfoList = unionInfo.getMemberInfoList();
        for (CrossBiaoJuUserInfo memberInfo : memberInfoList) {
            if (memberInfo.getUserData().getUserId() == userId) {
                continue;
            }

            if (!memberInfo.checkCanBePull(dartConfig.getGear(), userId)) {
                continue;
            }

            BiaoJuProto.BiaoJuUserTemp.Builder builder = parseUserTemp(memberInfo);
            respMsg.addMemberList(builder);
        }

        return respMsg;
    }

    public BiaoJuProto.BiaoJuPullTargetInTeamRespMsg.Builder pullTargetInTeam(long userId, List<Long> targetUserIds) {
        BiaoJuProto.BiaoJuPullTargetInTeamRespMsg.Builder respMsg = BiaoJuProto.BiaoJuPullTargetInTeamRespMsg.newBuilder();
        respMsg.setRet(0);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        checkUserRunEscortEnd(userInfo);

        synchronized (unionInfo) {
            CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
            if (runEscortData == null) {
                return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_TAKE_ESCORT);
            }

            if (runEscortData.getBattleLogList().size() > 0) {
                return respMsg.setRet(GameErrorCode.E_BIAOJU_RUNNING_ESCORT);
            }

            if (runEscortData.getTeamUserList().size() + targetUserIds.size() > config.getTeamJoinLimit()) {
                return respMsg.setRet(GameErrorCode.E_BIAOJU_TEAM_JOIN_NUM_LIMIT);
            }

            BiaoJuDartConfig dartConfig = config.getDartConfig(runEscortData.getEscortId());
            if (dartConfig == null) {
                return respMsg.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
            }

            for (Long targetUserId : targetUserIds) {
                CrossBiaoJuUserInfo targetUserInfo = getUserInfoOnlyGet(targetUserId);
                if (targetUserInfo == null) {
                    return respMsg.setRet(GameErrorCode.E_BIAOJU_TARGET_NOT_ABLE);
                }

                if (!targetUserInfo.checkCanBePull(dartConfig.getGear(), userId)) {
                    return respMsg.setRet(GameErrorCode.E_BIAOJU_PULL_QUALITY_ERR);
                }

                if (!targetUserInfo.checkDayJoinNumLimit(config.getDayJoinLimit())) {
                    return respMsg.setRet(GameErrorCode.E_BIAOJU_DAY_JOIN_NUM_LIMIT);
                }

                if (runEscortData.getTeamUserList().stream().anyMatch(e -> e.getUserId() == targetUserId)) {
                    return respMsg.setRet(GameErrorCode.E_BIAOJU_ESCORT_JOINED);
                }
            }

            if (runEscortData.getTeamUserList().size() + targetUserIds.size() > config.getTeamJoinLimit()) {
                return respMsg.setRet(GameErrorCode.E_BIAOJU_TEAM_JOIN_NUM_LIMIT);
            }

            for (Long targetUserId : targetUserIds) {
                CrossBiaoJuUserInfo targetUserInfo = getUserInfoOnlyGet(targetUserId);
                if (!targetUserInfo.checkDayJoinNumLimit(config.getDayJoinLimit())) {
                    continue;
                }
                int ret = userInfo.addTeamUser(targetUserId, targetUserInfo.getUserData().getLevel(), config.getTeamJoinLimit());
                if (ret == 0) {
                    targetUserInfo.addDayJoinNum();
                }
            }

            refreshRunEscortBattleValue(runEscortData);

            respMsg.setEscortInfo(parseEscortDetail(runEscortData, userId));
        }

        addNeedSyncUnion(unionInfo);

        return respMsg;
    }

    public BiaoJuProto.BiaoJuEscortConfirmFinishRespMsg.Builder confirmFinishEscort(long userId, int type) {
        BiaoJuProto.BiaoJuEscortConfirmFinishRespMsg.Builder respMsg = BiaoJuProto.BiaoJuEscortConfirmFinishRespMsg.newBuilder();
        respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_FINISH);
        respMsg.setType(type);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return respMsg;
        }

        CrossBiaoJuUserInfo userInfo = userInfoMap.get(userId);
        if (userInfo == null) {
            return respMsg;
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return respMsg;
        }

        if (type == 0) {
            CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
            if (runEscortData == null) {
                CrossBiaoJuUserRunEscortData lastNotConfirmHistoryEscort = userInfo.getLastNotConfirmHistoryEscort();
                if (lastNotConfirmHistoryEscort != null) {
                    BiaoJuProto.BiaoJuFinishEscortTemp.Builder finishBuilder = BiaoJuProto.BiaoJuFinishEscortTemp.newBuilder();
                    finishBuilder.setDetailInfo(parseEscortDetail(lastNotConfirmHistoryEscort, userId));
                    finishBuilder.setReward(lastNotConfirmHistoryEscort.getLeaderReward());
                    respMsg.setFinishEscort(finishBuilder);
                    respMsg.setRet(0);
                }
            }
        } else if (type == 1) {
            //找到作为队友的镖
            List<CrossBiaoJuUserInfo> memberInfoList = unionInfo.getMemberInfoList();
            for (CrossBiaoJuUserInfo biaoJuUserInfo : memberInfoList) {
                List<CrossBiaoJuUserRunEscortData> lastNotConfirmHistoryEscortByJoinList = biaoJuUserInfo.getLastNotConfirmHistoryEscortByJoin(userInfo.getUserData().getLastConfirmFinishTime(), userId);
                for (CrossBiaoJuUserRunEscortData runEscortDataByJoin : lastNotConfirmHistoryEscortByJoinList) {
                    BiaoJuProto.BiaoJuFinishEscortTemp.Builder finishBuilder = BiaoJuProto.BiaoJuFinishEscortTemp.newBuilder();
                    finishBuilder.setDetailInfo(parseEscortDetail(runEscortDataByJoin, userId));
                    finishBuilder.setReward(runEscortDataByJoin.getReward());
                    respMsg.addFinishEscortByJoin(finishBuilder);
                    respMsg.setRet(0);
                }
            }
        } else if (type == 2) {
            CrossBiaoJuUserRunEscortData runEscortData = userInfo.getRunEscortData();
            if (runEscortData == null) {
                CrossBiaoJuUserRunEscortData lastNotConfirmHistoryEscort = userInfo.getLastNotConfirmHistoryEscort();
                if (lastNotConfirmHistoryEscort != null) {
                    BiaoJuProto.BiaoJuFinishEscortTemp.Builder finishBuilder = BiaoJuProto.BiaoJuFinishEscortTemp.newBuilder();
                    finishBuilder.setDetailInfo(parseEscortDetail(lastNotConfirmHistoryEscort, userId));
                    finishBuilder.setReward(lastNotConfirmHistoryEscort.getLeaderReward());
                    respMsg.setFinishEscort(finishBuilder);
                    respMsg.setRet(0);
                }
            }
            //找到作为队友的镖
            List<CrossBiaoJuUserInfo> memberInfoList = unionInfo.getMemberInfoList();
            for (CrossBiaoJuUserInfo biaoJuUserInfo : memberInfoList) {
                List<CrossBiaoJuUserRunEscortData> lastNotConfirmHistoryEscortByJoinList = biaoJuUserInfo.getLastNotConfirmHistoryEscortByJoin(userInfo.getUserData().getLastConfirmFinishTime(), userId);
                for (CrossBiaoJuUserRunEscortData runEscortDataByJoin : lastNotConfirmHistoryEscortByJoinList) {
                    BiaoJuProto.BiaoJuFinishEscortTemp.Builder finishBuilder = BiaoJuProto.BiaoJuFinishEscortTemp.newBuilder();
                    finishBuilder.setDetailInfo(parseEscortDetail(runEscortDataByJoin, userId));
                    finishBuilder.setReward(runEscortDataByJoin.getReward());
                    respMsg.addFinishEscortByJoin(finishBuilder);
                    respMsg.setRet(0);
                }
            }
        }

        userInfo.getUserData().setLastConfirmFinishTime(DateHelper.getCurrentTime());

        return respMsg;
    }

    public void addNeedSyncUser(long userId) {
        CrossBiaoJuUserInfo userInfo = userInfoMap.get(userId);
        if (userInfo == null) {
            return;
        }
        synchronized (needSyncUserSet) {
            needSyncUserSet.add(userId);
        }
    }

    private void addNeedSyncUnion(CrossBiaoJuUnionInfo unionInfo) {
        List<CrossBiaoJuUserInfo> memberInfoList = unionInfo.getMemberInfoList();
        for (CrossBiaoJuUserInfo biaoJuUserInfo : memberInfoList) {
            addNeedSyncUser(biaoJuUserInfo.getUserData().getUserId());
        }
    }

    public void syncUserData() {
        List<Long> userIds = new ArrayList<>();
        synchronized (needSyncUserSet) {
            userIds.addAll(needSyncUserSet);
            needSyncUserSet.clear();
        }

        for (Long userId : userIds) {
            syncUserData(userId);
        }
    }

    public void debugByCmd(long userId, ZhenHuanProto.CrossZhenHuanThirdProcessDebugReqMsg reqMsg) {
        BiaoJuConfig config = getConfig();
        String code = reqMsg.getCode();
        if (code.equals("/bj-money")) {
            int moneyAdd = Integer.valueOf(reqMsg.getParam());
            CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
            if (userInfo != null) {
                userInfo.getUserData().setMoney(userInfo.getUserData().getMoney() + moneyAdd);
            }
        } else if (code.equals("/bj-level")) {
            int level = Integer.valueOf(reqMsg.getParam());
            BiaoJuTitleConfig biaoJuTitleConfig = config.getTitleConfigMap().get(level);
            if (biaoJuTitleConfig == null) {
                return;
            }
            int exp = biaoJuTitleConfig.getCost();
            CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
            if (userInfo != null) {
                userInfo.getUserData().setLevel(level);
                userInfo.getUserData().setExp(exp);
            }
        } else if (code.equals("/bj-best")) {
            CrossBiaoJuBestEscortRoundInfo crossBiaoJuBestEscortRoundInfo = bestEscortRoundInfoMap.get(config.getNowRound());
            if (crossBiaoJuBestEscortRoundInfo != null) {
                createBestEscort(crossBiaoJuBestEscortRoundInfo);
            }
        }
    }

    public BiaoJuProto.BiaoJuCityBuildContributionListRespMsg.Builder getCityBuildContributionList(long userId, int cityId) {
        BiaoJuProto.BiaoJuCityBuildContributionListRespMsg.Builder respMsg = BiaoJuProto.BiaoJuCityBuildContributionListRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setCityId(cityId);

        BiaoJuConfig config = getConfig();
        if (config == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_CONFIG_NOT_FOUND);
        }

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuCityData cityData = unionInfo.getCityDataMap().get(cityId);
        if (cityData == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_CITY_NOT_FOUND);
        }

        Map<Long, Long> nowRoundScoreMap = new HashMap<>();
        Map<Long, Long> nowRoundLastBuildTime = new HashMap<>();
        Map<Long, Long> amountRoundScoreMap = new HashMap<>();
        Map<Long, Long> dayScoreMap = new HashMap<>();

        synchronized (unionInfo) {
            for (Map.Entry<Integer, Map<Long, BiaoJuCityUserBuildInfo>> entry : cityData.getMemberAddScoreMap().entrySet()) {
                Integer round = entry.getKey();
                for (Map.Entry<Long, BiaoJuCityUserBuildInfo> infoEntry : entry.getValue().entrySet()) {
                    Long memberId = infoEntry.getKey();
                    BiaoJuCityUserBuildInfo info = infoEntry.getValue();
                    if (config.getNowRound() == round) {
                        nowRoundScoreMap.put(memberId, info.getScoreAdd());
                        nowRoundLastBuildTime.put(memberId, info.getLastAddTime());
                    }
                    Long amountScore = amountRoundScoreMap.getOrDefault(memberId, 0l);
                    amountRoundScoreMap.put(memberId, amountScore + info.getScoreAdd());

                    if (config.isTodayRound(round)) {
                        Long dayScore = dayScoreMap.getOrDefault(memberId, 0l);
                        dayScoreMap.put(memberId, dayScore + info.getScoreAdd());
                    }
                }
            }
        }

        List<CrossBiaoJuUserInfo> memberInfoList = unionInfo.getMemberInfoList();
        for (CrossBiaoJuUserInfo biaoJuUserInfo : memberInfoList) {
            BiaoJuProto.BiaoJuCityBuildContributionTemp.Builder builder = BiaoJuProto.BiaoJuCityBuildContributionTemp.newBuilder();
            builder.setUserId(biaoJuUserInfo.getUserData().getUserId());
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(biaoJuUserInfo.getUserData().getUserId());
            if (userBaseInfo == null) {
                continue;
            }
            builder.setUserName(userBaseInfo.getNickName());
            builder.setNowRoundScore(nowRoundScoreMap.getOrDefault(builder.getUserId(), 0l));
            builder.setAmountRoundScore(amountRoundScoreMap.getOrDefault(builder.getUserId(), 0l));
            builder.setLastBuildTime(nowRoundLastBuildTime.getOrDefault(builder.getUserId(), 0l));
            builder.setDayScore(dayScoreMap.getOrDefault(builder.getUserId(), 0l));
            if (builder.getNowRoundScore() == 0 && builder.getAmountRoundScore() == 0) {
                continue;
            }

            respMsg.addContributionList(builder);
        }

        return respMsg;
    }

    public BiaoJuProto.BiaoJuUnionMemberListRespMsg.Builder getMemberInfoList(long userId) {
        BiaoJuProto.BiaoJuUnionMemberListRespMsg.Builder respMsg = BiaoJuProto.BiaoJuUnionMemberListRespMsg.newBuilder();
        respMsg.setRet(0);

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        List<Long> unionUserList = Cross2UnionActivityGroupMgr.getUnionUserList(activityId, userInfo.getUserData().getUnionId());
        for (Long memberId : unionUserList) {
            CrossBiaoJuUserInfo biaoJuUserInfo = getUserInfoOnlyGet(memberId);
            if (biaoJuUserInfo != null) {
                respMsg.addMemberList(parseUserTemp(biaoJuUserInfo));
            }else {
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(memberId);
                if (userBaseInfo == null) {
                    continue;
                }
                respMsg.addMemberList(parseEmptyUserTemp(memberId));
            }
        }

        int myUnionRank = unionInfo.getUnionData().getRank();
        UnionActivityRankProto.UnionActivityRankListMsg unionRankBuild = getUnionRankBuild();
        if (myUnionRank > unionRankBuild.getRankListCount()) {
            myUnionRank = -1;
        }

        respMsg.setUnionRank(myUnionRank);

        return respMsg;
    }

    public void addLockBestEscortNotice(CrossBiaoJuUserRunEscortData runEscortData) {
        BiaoJuProto.BiaoJuLockBestEscortNoticeTemp.Builder noticeBuilder = parseLockBestEscortNotice(runEscortData);
        if (noticeBuilder == null) {
            return;
        }
        synchronized (lockBestEscortNoticeTempList) {
            lockBestEscortNoticeTempList.add(noticeBuilder.build());

            while (lockBestEscortNoticeTempList.size() > getConfig().getNoticeNum()) {
                lockBestEscortNoticeTempList.remove(0);
            }
        }

        BiaoJuProto.BiaoJuUserLockBestEscortNoticeMsg.Builder syncMsg = BiaoJuProto.BiaoJuUserLockBestEscortNoticeMsg.newBuilder();
        syncMsg.setNotice(noticeBuilder);

        syncAllUserMsg(0, ClientProtocol.U_BIAOJU_USER_LOCK_BEST_ESCORT_NOTICE, syncMsg);
    }

    public BiaoJuProto.BiaoJuUserLockBestEscortNoticeListRespMsg.Builder getUserLockBestEscortNoticeList(long userId) {
        BiaoJuProto.BiaoJuUserLockBestEscortNoticeListRespMsg.Builder respMsg = BiaoJuProto.BiaoJuUserLockBestEscortNoticeListRespMsg.newBuilder();
        respMsg.setRet(0);

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        List<BiaoJuProto.BiaoJuLockBestEscortNoticeTemp> noticeList = new ArrayList<>();
        synchronized (lockBestEscortNoticeTempList) {
            noticeList.addAll(lockBestEscortNoticeTempList);
        }

        respMsg.addAllNoticeList(noticeList);

        return respMsg;
    }

    public BiaoJuProto.BiaoJuGetEscortDetailRespMsg.Builder getEscortDetail(long userId, BiaoJuProto.BiaoJuGetEscortDetailReqMsg reqMsg) {
        BiaoJuProto.BiaoJuGetEscortDetailRespMsg.Builder respMsg = BiaoJuProto.BiaoJuGetEscortDetailRespMsg.newBuilder();
        respMsg.setRet(0);

        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        }

        for (BiaoJuProto.BiaoJuGetEscortDetailTemp reqInfo : reqMsg.getReqInfoList()) {
            long targetUserId = reqInfo.getUserId();
            int escortUniqueId = reqInfo.getEscortUniqueId();
            CrossBiaoJuUserInfo targetUserInfo = getUserInfoOnlyGet(targetUserId);
            if (targetUserInfo == null) {
                continue;
            }

            if (!targetUserInfo.getUserData().getUnionId().equals(userInfo.getUserData().getUnionId())) {
                continue;
            }

            CrossBiaoJuUserRunEscortData runEscortData = targetUserInfo.findEscortData(escortUniqueId);
            if (runEscortData == null) {
                continue;
            }

            BiaoJuProto.BiaoJuMemberEscortDetailTemp.Builder escortDetail = parseEscortDetail(runEscortData, userId);
            respMsg.addEscortDetailList(escortDetail);
        }

        return respMsg;
    }

    public void sendUnionRankMemberContribution(long userId, long serverId, String seeUnionUid) {
        StrongholdActivityProto.StrongholdActivityConditionUnionMemberDataRespMsg.Builder respMsg = StrongholdActivityProto.StrongholdActivityConditionUnionMemberDataRespMsg.newBuilder();
        respMsg.setRet(0);

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(seeUnionUid);
        if (unionInfo == null) {
            respMsg.setRet(GameErrorCode.E_BIAOJU_NOT_ABLE);
        } else {
            ActivityProto.ActivityConditionUnionMemberDataListMsg.Builder contributionBuilder = ActivityProto.ActivityConditionUnionMemberDataListMsg.newBuilder();

            List<CrossBiaoJuUserInfo> memberInfoList = unionInfo.getMemberInfoList();
            for (CrossBiaoJuUserInfo biaoJuUserInfo : memberInfoList) {
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(biaoJuUserInfo.getUserData().getUserId());
                if (userBaseInfo == null) {
                    continue;
                }
                ActivityProto.ActivityConditionUnionMemberDataTempMsg.Builder builder = ActivityProto.ActivityConditionUnionMemberDataTempMsg.newBuilder();
                builder.setUserId(biaoJuUserInfo.getUserData().getUserId());
                builder.setValue(String.valueOf(biaoJuUserInfo.getUserData().getUnionExpAdd()));
                builder.setNickName(userBaseInfo.getNickName());
                builder.setModifyTime(biaoJuUserInfo.getUserData().getLastBuildTime());
                contributionBuilder.addDataList(builder);
            }

            respMsg.setDataList(contributionBuilder);
        }

        YanQuMessage message = YanQuMessageUtils.buildMessage(Protocol.U_GENERAL_ACTIVITY_MEMBER_CONDITION_DATA, respMsg);
        MessageHelper.sendPacket(serverId, userId, message);
    }

    /**
     * 活动结束,更新商会职位
     */
    public void refreshUnionPosition() {
        BiaoJuConfig config = getConfig();
        if (config == null) {
            return;
        }

        if (checkActivityEndUnionPositionTime > 0) {
            return;
        }

        long currentTime = DateHelper.getCurrentTime();
        long currentSecond = currentTime / 1000;
        if (currentSecond < config.getActivityInfo().getEndTime() + 5 * DateHelper.MINUTE_SECONDS) {
            return;
        }

        checkActivityEndUnionPositionTime = currentTime;

        List<CrossBiaoJuUnionInfo> unionInfoList = getUnionInfoList();

        for (CrossBiaoJuUnionInfo biaoJuUnionInfo : unionInfoList) {
            UnionActivityGroupUnion unionData = Cross2UnionActivityGroupMgr.getUnionData(activityId, biaoJuUnionInfo.getUnionData().getUnionId(), unionGroup);
            if (unionData == null) {
                CrossBiaoJuMgr.getLogger().error("锁定职位时找不到商会分组数据 activityId:{} group:{} unionId:{}", activityId, unionGroup, biaoJuUnionInfo.getUnionData().getUnionId());
                continue;
            }

            for (UnionActivityGroupUser activityGroupUser : unionData.getUserMap().values()) {
                CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(activityGroupUser.getUserId());
                if (userInfo == null) {
                    continue;
                }

                userInfo.getUserData().setUnionPos(activityGroupUser.getPosition());
            }
        }
    }

    public List<CrossBiaoJuUserInfo> getUserInfoList() {
        List<CrossBiaoJuUserInfo> list = new ArrayList<>();
        synchronized (userInfoMap) {
            list.addAll(userInfoMap.values());
        }

        return list;
    }

    public List<CrossBiaoJuUnionInfo> getUnionInfoList() {
        List<CrossBiaoJuUnionInfo> list = new ArrayList<>();
        synchronized (unionInfoMap) {
            list.addAll(unionInfoMap.values());
        }

        return list;
    }

    public void autoSendUserRank(long serverId) {
        AutoSendRewardProto.CrossUserRankMsg.Builder builder = AutoSendRewardProto.CrossUserRankMsg.newBuilder();
        builder.setActivityId(activityId);
        List<CrossBiaoJuUserInfo> userInfoList = getUserInfoList();
        for (CrossBiaoJuUserInfo biaoJuUserInfo : userInfoList) {
            builder.addData(AutoSendRewardProto.UserRankMsg.newBuilder()
                    .setUserId(biaoJuUserInfo.getUserData().getUserId())
                    .setRank(biaoJuUserInfo.getUserData().getRank())
                    .setConditionType(eGamePlayerEventType.BiaoJuExpRank.getValue())
            );
        }

        YanQuMessage message = YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_ACTIVITY_AUTO_SEND_USER_REWARD, builder);
        MessageHelper.sendPacket(serverId, 0, message);
    }

    public void autoSendUnionRank(long serverId) {
        List<CrossBiaoJuUnionInfo> unionInfoList = getUnionInfoList();

        AutoSendRewardProto.CrossUnionRankMsg.Builder builder = AutoSendRewardProto.CrossUnionRankMsg.newBuilder();
        builder.setActivityId(activityId);

        for (CrossBiaoJuUnionInfo biaoJuUnionInfo : unionInfoList) {
            int rank = biaoJuUnionInfo.getUnionData().getRank();

            AutoSendRewardProto.UnionRankMsg.Builder unionBuilder = AutoSendRewardProto.UnionRankMsg.newBuilder();
            unionBuilder.setUnionId(biaoJuUnionInfo.getUnionData().getUnionId());
            unionBuilder.setRank(rank);
            unionBuilder.setConditionType(eGamePlayerEventType.BiaoJuUnionExpRank.getValue());

            for (CrossBiaoJuUserInfo biaoJuUserInfo : biaoJuUnionInfo.getMemberInfoList()) {
                long userId = biaoJuUserInfo.getUserData().getUserId();
                long userServerId = CrossUserMgr.getServerIdByUserId(userId);
                if (serverId != userServerId) {
                    continue;
                }
                int pos = biaoJuUserInfo.getUserData().getUnionPos();

                CrossUnionActivityRankDataProto.CrossUnionMemberPosDataMsg.Builder posBuilder = CrossUnionActivityRankDataProto.CrossUnionMemberPosDataMsg.newBuilder();
                posBuilder.setUserId(userId);
                posBuilder.setPos(pos);

                unionBuilder.addPosList(posBuilder);
            }

            builder.addData(unionBuilder);
        }

        YanQuMessage message = YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_ACTIVITY_AUTO_SEND_UNION_REWARD, builder);
        MessageHelper.sendPacket(serverId, 0, message);
    }

    public int getMaxBestQuality() {
        int maxQuality = 0;
        for (Integer quality : biaoJuData.getBestQualityList()) {
            if (quality > maxQuality) {
                maxQuality = quality;
            }
        }

        return maxQuality;
    }

    public int getMinBestQuality() {
        int minQuality = 0;
        for (Integer quality : biaoJuData.getBestQualityList()) {
            if (minQuality == 0) {
                minQuality = quality;
            }
            if (quality < minQuality) {
                minQuality = quality;
            }
        }

        return minQuality;
    }

    public long getUserRoundBuildNum(long userId, int round) {
        CrossBiaoJuUserInfo userInfo = getUserInfoOnlyGet(userId);
        if (userInfo == null) {
            return 0;
        }

        CrossBiaoJuUnionInfo unionInfo = getUnionInfo(userInfo.getUserData().getUnionId());
        if (unionInfo == null) {
            return 0;
        }

        long roundBuildNum = 0;
        for (CrossBiaoJuCityData cityData : unionInfo.getCityDataMap().values()) {
            long memberAddScore = cityData.getMemberAddScore(round, userId);
            roundBuildNum += memberAddScore;
        }

        return roundBuildNum;
    }
}
